java lang null打印结果最后出现null值怎么修复(删掉)?

java 在表格中显示mysql查询结果中(包含有空值)的显示问题_百度知道
java 在表格中显示mysql查询结果中(包含有空值)的显示问题
问题如下:
在数据库中的查询结果如下,但是在但是到了java编程JTable中就无法正常显示了,求简单一点的实现方案~
提示错误的部分代码如下:
运行结果如下:
如果把Grade属性去了就能正常显示(我的目的是要显示Grade当然不可以去了这个属性,求解决方案...
答题抽奖
首次认真答题后
即可获得3次抽奖机会,100%中奖。
直接方案不要用“new String()”,改成String.valueOf()第二套方案在写Vector的类型可以改成:Vector&Object&rs.getObject(i+1)Vector类型Vect it’s only in the library for legacy code support这个类型在java1.1就有了,至今已经不用了,留着它是为了,防止破坏老代码所以这里你可以用List&Object[]&
采纳率:36%
这很简单,在sql,Grade字段上添加,ifnull函数,可以解决
判断一下就行了,为空就录入“”;这里是因为字段为null导致异常,你也可以数据库中设置grade字段默认值“”,这样也不会报错
在你的语句里面添加一下 , ifnull(Grade,'') , 判断为null时,赋值为空字符串
需要改一行代码temp.add(new&String(rs.getString(i+1)+&&));
1、getString获得的就是String类型,不用new String()了2、我记得JTable会自动把null值变空字符串,你空指针是因为new String,直接去掉试试,不行再看33、那句改成temp.add(rs.getString(i + 1) == null ? && : rs.getString(i + 1)),或者你加if判断也行
你的方法也可以,不过只能采纳一个,给先回答的吧。谢谢了~
其他3条回答
为您推荐:
其他类似问题
mysql的相关知识
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。Java核心技术 卷Ⅰ 基础知识(原书第10版)
Java核心技术系列
Java核心技术
卷Ⅰ 基础知识
(原书第10版)
Core Java Volume I—Fundamentals (10th Edition)
[美] 凯S.霍斯特曼(Cay S. Horstmann) 著
周立新 陈 波 叶乃文 邝劲筠 杜永萍 译
图书在版编目(CIP)数据
Java核心技术 卷Ⅰ 基础知识(原书第10版) / (美)凯S. 霍斯特曼(Cay S. Horstmann)著;周立新等译. —北京:机械工业出版社,2016.8
(Java核心技术系列)
书名原文:Core Java Volume I—Fundamentals (Tenth Edition)
ISBN 978-7-111-54742-6
I. J… II. ①凯… ②周… III. JAVA语言-程序设计 IV. TP312.8
中国版本图书馆CIP数据核字(2016)第211440号
本书版权登记号:图字:01-
Authorized translation from the English language edition, entitled Core Java Volume I—Fundamentals (Tenth Edition),4 by Cay S. Horstmann, published by Pearson Education, Inc., Copyright ? 2016 Oracle and /or its aff?iliates.
All rights reserved. No part of this book may be reproduced or transmitted in any form or by any means, electronic or mechanical, including photocopying, recording or by any information storage retrieval system, without permission from Pearson Education, Inc.
Chinese Simplif?ied language edition published by Pearson Education Asia Ltd., and China Machine Press Copyright ? 2016.
本书中文简体字版由Pearson Education(培生教育出版集团)授权机械工业出版社在中华人民共和国境内(不包括香港、澳门特别行政区及台湾地区)独家出版发行。未经出版者书面许可,不得以任何方式抄袭、复制或节录本书中的任何部分。
本书封底贴有Pearson Education(培生教育出版集团)激光防伪标签,无标签者不得销售。
Java核心技术 卷Ⅰ 基础知识(原书第10版)
出版发行:机械工业出版社(北京市西城区百万庄大街22号 邮政编码:100037)
责任编辑:关 敏 责任校对:董纪丽
印  刷: 版  次:2016年9月第1版第1次印刷
开  本:186mm×240mm 1/16 印  张:45.5
书  号:ISBN 978-7-111-54742-6 定  价:119.00元
凡购本书,如有缺页、倒页、脱页,由本社发行部调换
客服热线:(010)361066 投稿热线:(010)
购书热线:(010)995259 读者信箱:
版权所有 ? 侵权必究
封底无防伪标均为盗版
本书法律顾问:北京大成律师事务所 韩光/邹晓东
译 者 序
书写Java传奇的Sun Microsystems曾经堪称“日不落”帝国,但服务器市场的萎缩却让这个声名赫赫的庞大帝国从蓬勃走向落寞。在2009年被Oracle公司收购之后,Sun公司逐渐淡出了人们的视线,而与此同时,我们也在很长一段时间内没能看到Java当初活跃的身影。
Java就这样退出历史舞台了吗?当然不是!从Sun公司2006年12月发布Java 6后,经过5年多的不懈努力,终于在2011年7月底发布了Java 7正式版。3年后,被冠名为“跳票王”的Oracle终于发布了Java 8的正式版,但对于很多开发者来说,Java 8却比Java 7来得更漫长一些。主要是因为Oracle原本计划在2013年发布正式版Java 8,却因受困于安全性的问题经过了两次“跳票”。无论如何,如今Java 8来了,全新“革命”而不只是“进化”的功能将会让无数开发者动容。
值得一提的是,伴随着Java的成长,《Java核心技术》也从第1版到第9版一路走来,得到了广大Java程序设计人员的青睐,成为一本畅销不衰的Java经典图书。经过几年的蛰伏,针对Java 8打造的《Java核心技术》第10版终于问世,这一版有了大幅的修订和更新,以反映Java 8增补、删改的内容。它将续写从前的辉煌,使人们能及时跟上Java前进的脚步。
本书由周立新、陈波等主译,程芳、刘晓兵、张练达、陈峰、江健、谢连宝、张雷生、杨健康、张莹参与了全书的修改整理,并完善了关键部分的翻译。全体人员共同完成了本书的翻译工作。特别需要说明的是,按照出版社的要求,这一版的翻译在老版本基础上完成,因此尤其感谢之前版本的译者叶乃文、邝劲筠和杜永萍,他们的辛勤工作为新版本的翻译奠定了很好的基础。
书中文字与内容力求忠实原著,不过由于译者水平有限,译文肯定有不当之处,敬请批评指正。
2016年6月于北京
1995年年底,Java语言在Internet舞台一亮相便名声大噪。其原因在于它将有望成为连接用户与信息的万能胶,而不论这些信息来自Web服务器、数据库、信息提供商,还是任何其他渠道。事实上,就发展前景而言,Java的地位是独一无二的。它是一种完全可信赖的程序设计语言,得到了除微软之外的所有厂家的认可。其固有的可靠性与安全性不仅令Java程序员放心,也令使用Java程序的用户放心。Java内建了对网络编程、数据库连接、多线程等高级程序设计任务的支持。
1995年以来,已经发布了Java开发工具包(Java Development Kit)的9个主要版本。在过去的20年中,应用程序编程接口(API)已经从200个类扩展到超过4000个类。现在这些API覆盖了用户界面构建、数据库管理、国际化、安全性以及XML处理等各个不同的领域。
本书是《Java核心技术》第10版的卷Ⅰ。自《Java核心技术》出版以来,每个新版本都尽可能快地跟上Java开发工具箱发展的步伐,而且每一版都重新改写了部分内容,以便适应Java的最新特性。在这一版中,已经反映了Java 标准版(Java SE 8)的特性。
与前几版一样,本版仍然将读者群定位在那些打算将Java应用到实际工程项目中的程序设计人员。本书假设读者是一名具有程序设计语言(除Java之外)坚实背景知识的程序设计人员,并且不希望书中充斥着玩具式的示例(诸如,烤面包机、动物园的动物或神经质的跳动文本)。这些内容绝对不会在本书中出现。本书的目标是让读者充分理解书中介绍的Java语言及Java类库的相关特性,而不会产生任何误解。
在本书中,我们选用大量的示例代码演示所讨论的每一个语言特性和类库特性。我们有意使用简单的示例程序以突出重点,然而,其中的大部分既不是赝品也没有偷工减料。它们将成为读者自己编写代码的良好开端。
我们假定读者愿意(甚至渴望)学习Java提供的所有高级特性。例如,本书将详细介绍下列内容:
面向对象程序设计
反射与代理
接口与内部类
泛型程序设计
事件监听器模型
使用Swing UI工具箱进行图形用户界面设计
随着Java类库的爆炸式增长,一本书无法涵盖程序员需要了解的所有Java特性。因此,我们决定将本书分为两卷。卷I(本书)集中介绍Java语言的基本概念以及图形用户界面程序设计的基础知识。卷Ⅱ(高级特性)涉及企业特性以及高级的用户界面程序设计,其中详细讨论下列内容:
文件处理与正则表达式
高级GUI组件
本书中难免出现错误和不准确之处。我们很想知道这些错误,当然,也希望同一个问题只被告知一次。我们在网页http://horstmann.com/corejava中以列表的形式给出了常见的问题、bug修正和解决方法。在勘误页(建议先阅读一遍)最后附有用来报告bug并提出修改意见的表单。如果我们不能回答每一个问题或没有及时回复,请不要失望。我们会认真地阅读所有的来信,感谢您的建议使本书后续的版本更清晰、更有指导价值。
第1章概述Java与其他程序设计语言不同的性能。解释这种语言的设计初衷,以及在哪些方面达到了预期的效果。然后,简要叙述Java诞生和发展的历史。
第2章详细论述如何下载和安装JDK以及本书的程序示例。然后,通过编译和运行3个典型的Java程序(一个控制台应用、一个图形应用、一个applet),指导读者使用简易的JDK、可启用Java的文本编辑器以及一个Java IDE。
第3章开始讨论Java 语言。这一章涉及的基础知识有变量、循环以及简单的函数。对于C或C++程序员来说,学习这一章的内容将会感觉一帆风顺,因为这些语言特性的语法本质上与C语言相同。对于没有C语言程序设计背景,但使用过其他程序设计语言(如Visual Basic)的程序员来说,仔细地阅读这一章是非常必要的。
面向对象程序设计(Object-Oriented Programming, OOP)是当今程序设计的主流,而Java是一种完全面向对象的语言。第4章将介绍面向对象两个基本成分中最重要的——封装,以及Java语言实现封装的机制,即类与方法。除了Java语言规则之外,还对如何完成合理的OOP设计给出了忠告。最后,介绍奇妙的javadoc工具,它将代码注释转换为一组包含超链接的网页。熟悉C++的程序员可以快速地浏览这一章,而没有面向对象程序设计背景的程序员应在进一步学习Java之前花一些时间了解OOP的有关概念。
类与封装仅仅是OOP中的一部分,第5章将介绍另一部分——继承。继承使程序员可以使用现有的类,并根据需要进行修改。这是Java程序设计中的一个基础技术。Java中的继承机制与C++的继承机制十分相似。C++程序员只需关注两种语言的不同之处即可。
第6章展示如何使用Java的接口。接口可以让你的理解超越第5章的简单继承模型。掌握接口可以充分获得Java的完全的面向对象程序设计能力。介绍接口之后,我们将转而介绍lambda表达式(lambda expression),这是一种简洁的方法,用来表述可以在以后某个时间点执行的代码块。本章还将介绍Java的一个有用的技术特性——内部类。
第7章讨论异常处理(exception handling),即Java的一种健壮机制,用于处理可正常运行程序可能出现意外的情况。异常提供了一种将正常处理代码与错误处理代码分开的有效手段。当然,即使程序能够处理所有异常条件,仍然有可能无法按照预计的方式工作。这一章的后半部分将给出大量实用的调试技巧。
第8章概要介绍泛型程序设计。泛型程序设计可以让程序更可读、更安全。我们会展示如何使用强类型机制,而舍弃不安全的强制类型转换,以及如何处理与旧版本Java兼容所带来的复杂问题。
第9章讨论的是Java平台的集合框架。如果希望收集多个对象并在以后获取这些对象,就应当使用集合,而不要简单地把这些元素放在一个数组中,这是这种情况下最适用的做法。这一章会介绍如何充分利用内建的标准集合。
第10章开始介绍GUI程序设计。我们会讨论如何建立窗口、如何在窗口中绘图、如何利用几何图形绘图、如何采用多种字体格式化文本,以及如何显示图像。
第11章将详细讨论抽象窗口工具包(abstract window toolkit,AWT)的事件模型。你会看到如何编写代码来响应事件,如鼠标点击事件或按键事件。同时,你还会看到如何处理基本的GUI元素,如按钮和面板。
第12章详细讨论Swing GUI工具包。Swing工具包允许建立跨平台的图像用户界面。在这里你会了解各种按钮、文本组件、边框、滑块、列表框、菜单以及对话框的有关内容。不过,一些更高级的组件会在卷II中讨论。
第13章介绍如何将程序部署为应用或applet。在这里我们会描述如何将程序打包在JAR文件中,以及如何使用Java Web Start和applet机制在Internet上发布应用。另外还会解释Java程序部署之后如何存储和获取配置信息。
第14章是本书的最后一章,这一章将讨论并发,并发能够让程序任务并行执行。在当今这个时代,大多数处理器都有多个内核,你往往希望这些内核都在工作,并发是Java技术的一个重要而且令人振奋的应用。
附录列出了Java语言的保留字。
本书使用以下图标表示特殊内容。
注释:“注释”信息会用这样的“注释”图标标志。
提示:“提示”信息会用这样的“提示”图标标志。
警告:对于可能出现的危险,我们用一个“警告”图标做出警示。
C++注释:在本书中有许多用来解释Java与C++之间差别的C++注释。对于没有C++程序设计背景,或者不擅长C++程序设计、把它当做一场噩梦不愿再想起的程序员来说,可以跳过这些注释。
Java提供了一个很大的程序设计库,即应用程序编程接口。第一次使用API调用时,我们会在该节的结尾给出一个概要描述。这些描述十分通俗易懂,希望能够比联机API文档提供更多的信息。类、接口或方法名后面的编号是介绍该特性的JDK版本号,如下例所示:
应用程序编程接口1.2
程序(源代码见本书网站)以程序清单形式给出,例如:
程序清单1-1 InputTest/InputTest.java
本书网站http://horstmann.com/corejava以压缩的形式提供了书中的所有示例代码。可以用熟悉的解压缩程序或者用Java开发包中的jar实用程序解压这个文件。有关安装Java开发包和示例代码的详细信息请参看第2章。
写一本书需要投入大量的精力,改写一本书也并不像想象的那样轻松,尤其是Java技术一直在持续不断地更新。编著一本书让很多人耗费了很多心血,在此衷心地感谢《Java核心技术》编写小组的每一位成员。
Prentice Hall公司的许多人提供了非常有价值的帮助,却甘愿做幕后英雄。在此,我希望每一位都能够知道我对他们努力的感恩。与以往一样,我要真诚地感谢我的编辑,Prentice Hall公司的Greg Doench,从本书的写作到出版他一直在给予我们指导,同时感谢那些不知其姓名的为本书做出贡献的幕后人士。非常感谢Julie Nahil在图书制作方面给予的支持,还要感谢Dmitry Kirsanov和Alina Kirsanova完成手稿的编辑和排版工作。我还要感谢早期版本中我的合作者,Gary Cornell,他已经转向其他的事业。
感谢早期版本的许多读者,他们指出了许多令人尴尬的错误并给出了许多具有建设性的修改意见。我还要特别感谢本书优秀的审阅小组,他们仔细地审阅我的手稿,使本书减少了许多错误。
本书及早期版本的审阅专家包括:Chuck Allison (Utah Valley大学)、Lance Andersen (Oracle)、Paul Anderson (Anderson Software Group)、Alec Beaton (IBM)、Cliff Berg、Andrew Binstock (Oracle)、Joshua Bloch、David Brown、Corky Cartwright、Frank Cohen (PushToTest)、Chris Crane (devXsolution)、Dr. Nicholas J. De Lillo (Manhattan学院)、Rakesh Dhoopar (Oracle)、David Geary (Clarity Training)、Jim Gish (Oracle)、Brian Goetz (Oracle)、Angela Gordon、Dan Gordon (Electric Cloud)、Rob Gordon、John Gray (Hartford大学)、Cameron Gregory (olabs.com)、Marty Hall (coreservlets.com公司)、Vincent Hardy (Adobe Systems)、Dan Harkey (San Jose州立大学)、William Higgins (IBM)、Vladimir Ivanovic (PointBase)、Jerry Jackson (CA Technologies)、Tim Kimmet (Walmart)、Chris Laffra、Charlie Lai (Apple)、Angelika Langer、Doug Langston、Hang Lau (McGill大学)、Mark Lawrence、Doug Lea (SUNY Oswego)、Gregory Longshore、Bob Lynch (Lynch Associates)、Philip Milne (consultant)、Mark Morrissey (Oregon研究院)、Mahesh Neelakanta (Florida Atlantic大学)、Hao Pham、Paul Philion、Blake Ragsdell、Stuart Reges (Arizona大学)、Rich Rosen (Interactive Data Corporation)、Peter Sanders (法国尼斯ESSI大学)、Dr. Paul Sanghera (San Jose州立大学Brooks学院)、Paul Sevinc (Teamup AG)、Devang Shah (Sun Microsystems)、Yoshiki Shibata、Bradley A. Smith、Steven Stelting (Oracle)、Christopher Taylor、Luke Taylor (Valtech)、George Thiruvathukal、Kim Topley (StreamingEdge)、Janet Traub、Paul Tyma (consultant)、Peter van der Linden、Christian Ullenboom、Burt Walsh、Dan Xu (Oracle)和John Zavgren (Oracle)。
Cay Horstmann
2015年11月于瑞士比尔
第1章 Java程序设计概述
1.1 Java程序设计平台
1.2 Java“白皮书”的关键术语
1.2.1 简单性
1.2.2 面向对象
1.2.3 分布式
1.2.4 健壮性
1.2.5 安全性
1.2.6 体系结构中立
1.2.7 可移植性
1.2.8 解释型
1.2.9 高性能
1.2.10 多线程
1.2.11 动态性
1.3 Java applet与Internet
1.4 Java发展简史
1.5 关于Java的常见误解
第2章 Java程序设计环境
2.1 安装Java开发工具包
2.1.1 下载JDK
2.1.2 设置JDK
2.1.3 安装库源文件和文档
2.2 使用命令行工具
2.3 使用集成开发环境
2.4 运行图形化应用程序
2.5 构建并运行applet
第3章 Java的基本程序设计结构
3.1 一个简单的Java应用程序
3.3 数据类型
3.3.1 整型
3.3.2 浮点类型
3.3.3 char类型
3.3.4 Unicode和char类型
3.3.5 boolean类型
3.4.1 变量初始化
3.4.2 常量
3.5 运算符
3.5.1 数学函数与常量
3.5.2 数值类型之间的转换
3.5.3 强制类型转换
3.5.4 结合赋值和运算符
3.5.5 自增与自减运算符
3.5.6 关系和boolean运算符
3.5.7 位运算符
3.5.8 括号与运算符级别
3.5.9 枚举类型
3.6 字符串
3.6.1 子串
3.6.2 拼接
3.6.3 不可变字符串
3.6.4 检测字符串是否相等
3.6.5 空串与Null串
3.6.6 码点与代码单元
3.6.7 String API
3.6.8 阅读联机API文档
3.6.9 构建字符串
3.7 输入输出
3.7.1 读取输入
3.7.2 格式化输出
3.7.3 文件输入与输出
3.8 控制流程
3.8.1 块作用域
3.8.2 条件语句
3.8.3 循环
3.8.4 确定循环
3.8.5 多重选择:switch语句
3.8.6 中断控制流程语句
3.9 大数值
3.10 数组
3.10.1 for each循环
3.10.2 数组初始化以及匿名数组
3.10.3 数组拷贝
3.10.4 命令行参数
3.10.5 数组排序
3.10.6 多维数组
3.10.7 不规则数组
第4章 对象与类
4.1 面向对象程序设计概述
4.1.2 对象
4.1.3 识别类
4.1.4 类之间的关系
4.2 使用预定义类
4.2.1 对象与对象变量
4.2.2 Java类库中的LocalDate类
4.2.3 更改器方法与访问器方法
4.3 用户自定义类
4.3.1 Employee类
4.3.2 多个源文件的使用
4.3.3 剖析Employee类
4.3.4 从构造器开始
4.3.5 隐式参数与显式参数
4.3.6 封装的优点
4.3.7 基于类的访问权限
4.3.8 私有方法
4.3.9 f?inal实例域
4.4 静态域与静态方法
4.4.1 静态域
4.4.2 静态常量
4.4.3 静态方法
4.4.4 工厂方法
4.4.5 main方法
4.5 方法参数
4.6 对象构造
4.6.1 重载
4.6.2 默认域初始化
4.6.3 无参数的构造器
4.6.4 显式域初始化
4.6.5 参数名
4.6.6 调用另一个构造器
4.6.7 初始化块
4.6.8 对象析构与f?inalize方法
4.7.1 类的导入
4.7.2 静态导入
4.7.3 将类放入包中
4.7.4 包作用域
4.8 类路径
4.8.1 设置类路径
4.9 文档注释
4.9.1 注释的插入
4.9.2 类注释
4.9.3 方法注释
4.9.4 域注释
4.9.5 通用注释
4.9.6 包与概述注释
4.9.7 注释的抽取
4.10 类设计技巧
第5章 继承
5.1 类、超类和子类
5.1.1 定义子类
5.1.2 覆盖方法
5.1.3 子类构造器
5.1.4 继承层次
5.1.5 多态
5.1.6 理解方法调用
5.1.7 阻止继承:f?inal类和方法
5.1.8 强制类型转换
5.1.9 抽象类
5.1.10 受保护访问
5.2 Object:所有类的超类
5.2.1 equals方法
5.2.2 相等测试与继承
5.2.3 hashCode方法
5.2.4 toString方法
5.3 泛型数组列表
5.3.1 访问数组列表元素
5.3.2 类型化与原始数组列表的兼容性
5.4 对象包装器与自动装箱
5.5 参数数量可变的方法
5.6 枚举类
5.7.1 Class类
5.7.2 捕获异常
5.7.3 利用反射分析类的能力
5.7.4 在运行时使用反射分析对象
5.7.5 使用反射编写泛型数组代码
5.7.6 调用任意方法
5.8 继承的设计技巧
第6章 接口、lambda表达式与内部类
6.1.1 接口概念
6.1.2 接口的特性
6.1.3 接口与抽象类
6.1.4 静态方法
6.1.5 默认方法
6.1.6 解决默认方法冲突
6.2 接口示例
6.2.1 接口与回调
6.2.2 Comparator接口
6.2.3 对象克隆
6.3 lambda表达式
6.3.1 为什么引入lambda表达式
6.3.2 lambda表达式的语法
6.3.3 函数式接口
6.3.4 方法引用
6.3.5 构造器引用
6.3.6 变量作用域
6.3.7 处理lambda表达式
6.3.8 再谈Comparator
6.4 内部类
6.4.1 使用内部类访问对象状态
6.4.2 内部类的特殊语法规则
6.4.3 内部类是否有用、必要和安全
6.4.4 局部内部类
6.4.5 由外部方法访问变量
6.4.6 匿名内部类
6.4.7 静态内部类
6.5.1 何时使用代理
6.5.2 创建代理对象
6.5.3 代理类的特性
第7章 异常、断言和日志
7.1 处理错误
7.1.1 异常分类
7.1.2 声明受查异常
7.1.3 如何抛出异常
7.1.4 创建异常类
7.2 捕获异常
7.2.1 捕获异常
7.2.2 捕获多个异常
7.2.3 再次抛出异常与异常链
7.2.4 f?inally子句
7.2.5 带资源的try语句
7.2.6 分析堆栈轨迹元素
7.3 使用异常机制的技巧
7.4 使用断言
7.4.1 断言的概念
7.4.2 启用和禁用断言
7.4.3 使用断言完成参数检查
7.4.4 为文档假设使用断言
7.5 记录日志
7.5.1 基本日志
7.5.2 高级日志
7.5.3 修改日志管理器配置
7.5.4 本地化
7.5.5 处理器
7.5.6 过滤器
7.5.7 格式化器
7.5.8 日志记录说明
7.6 调试技巧
第8章 泛型程序设计
8.1 为什么要使用泛型程序设计
8.1.1 类型参数的好处
8.1.2 谁想成为泛型程序员
8.2 定义简单泛型类
8.3 泛型方法
8.4 类型变量的限定
8.5 泛型代码和虚拟机
8.5.1 类型擦除
8.5.2 翻译泛型表达式
8.5.3 翻译泛型方法
8.5.4 调用遗留代码
8.6 约束与局限性
8.6.1 不能用基本类型实例化类型参数
8.6.2 运行时类型查询只适用于原始类型
8.6.3 不能创建参数化类型的数组
8.6.4 Varargs警告
8.6.5 不能实例化类型变量
8.6.6 不能构造泛型数组
8.6.7 泛型类的静态上下文中类型变量无效
8.6.8 不能抛出或捕获泛型类的实例
8.6.9 可以消除对受查异常的检查
8.6.10 注意擦除后的冲突
8.7 泛型类型的继承规则
8.8 通配符类型
8.8.1 通配符概念
8.8.2 通配符的超类型限定
8.8.3 无限定通配符
8.8.4 通配符捕获
8.9 反射和泛型
8.9.1 泛型Class类
8.9.2 使用Class&T&参数进行类型匹配
8.9.3 虚拟机中的泛型类型信息
第9章 集合
9.1 Java集合框架
9.1.1 将集合的接口与实现分离
9.1.2 Collection接口
9.1.3 迭代器
9.1.4 泛型实用方法
9.1.5 集合框架中的接口
9.2 具体的集合
9.2.1 链表
9.2.2 数组列表
9.2.3 散列集
9.2.4 树集
9.2.5 队列与双端队列
9.2.6 优先级队列
9.3.1 基本映射操作
9.3.2 更新映射项
9.3.3 映射视图
9.3.4 弱散列映射
9.3.5 链接散列集与映射
9.3.6 枚举集与映射
9.3.7 标识散列映射
9.4 视图与包装器
9.4.1 轻量级集合包装器
9.4.2 子范围
9.4.3 不可修改的视图
9.4.4 同步视图
9.4.5 受查视图
9.4.6 关于可选操作的说明
9.5.1 排序与混排
9.5.2 二分查找
9.5.3 简单算法
9.5.4 批操作
9.5.5 集合与数组的转换
9.5.6 编写自己的算法
9.6 遗留的集合
9.6.1 Hashtable类
9.6.2 枚举
9.6.3 属性映射
9.6.5 位集
第10章 图形程序设计
10.1 Swing概述
10.2 创建框架
10.3 框架定位
10.3.1 框架属性
10.3.2 确定合适的框架大小
10.4 在组件中显示信息
10.5 处理2D图形
10.6 使用颜色
10.7 文本使用特殊字体
10.8 显示图像
第11章 事件处理
11.1 事件处理基础
11.1.1 实例:处理按钮点击事件
11.1.2 简洁地指定监听器
11.1.3 实例:改变观感
11.1.4 适配器类
11.2 动作
11.3 鼠标事件
11.4 AWT事件继承层次
11.4.1 语义事件和底层事件
第12章 Swing用户界面组件
12.1 Swing和模型–视图–控制器设计模式
12.1.1 设计模式
12.1.2 模型–视图–控制器模式
12.1.3 Swing按钮的模型–视图–控制器分析
12.2 布局管理概述
12.2.1 边框布局
12.2.2 网格布局
12.3 文本输入
12.3.1 文本域
12.3.2 标签和标签组件
12.3.3 密码域
12.3.4 文本区
12.3.5 滚动窗格
12.4 选择组件
12.4.1 复选框
12.4.2 单选钮
12.4.3 边框
12.4.4 组合框
12.4.5 滑动条
12.5 菜单
12.5.1 菜单创建
12.5.2 菜单项中的图标
12.5.3 复选框和单选钮菜单项
12.5.4 弹出菜单
12.5.5 快捷键和加速器
12.5.6 启用和禁用菜单项
12.5.7 工具栏
12.5.8 工具提示
12.6 复杂的布局管理
12.6.1 网格组布局
12.6.2 组布局
12.6.3 不使用布局管理器
12.6.4 定制布局管理器
12.6.5 遍历顺序
12.7 对话框
12.7.1 选项对话框
12.7.2 创建对话框
12.7.3 数据交换
12.7.4 文件对话框
12.7.5 颜色选择器
12.8 GUI程序排错
12.8.1 调试技巧
12.8.2 让AWT机器人完成工作
第13章 部署Java应用程序
13.1 JAR文件
13.1.1 创建JAR文件
13.1.2 清单文件
13.1.3 可执行JAR文件
13.1.4 资源
13.1.5 密封
13.2 应用首选项的存储
13.2.1 属性映射
13.2.2 首选项API
13.3 服务加载器
13.4 applet
13.4.1 一个简单的applet
13.4.2 applet HTML标记和属性
13.4.3 使用参数向applet传递信息
13.4.4 访问图像和音频文件
13.4.5 applet上下文
13.4.6 applet间通信
13.4.7 在浏览器中显示信息项
13.4.8 沙箱
13.4.9 签名代码
13.5 Java Web Start
13.5.1 发布Java Web Start应用
13.5.2 JNLP API
第14章 并发
14.1 什么是线程
14.1.1 使用线程给其他任务提供机会
14.2 中断线程
14.3 线程状态
14.3.1 新创建线程
14.3.2 可运行线程
14.3.3 被阻塞线程和等待线程
14.3.4 被终止的线程
14.4 线程属性
14.4.1 线程优先级
14.4.2 守护线程
14.4.3 未捕获异常处理器
14.5 同步
14.5.1 竞争条件的一个例子
14.5.2 竞争条件详解
14.5.3 锁对象
14.5.4 条件对象
14.5.5 synchronized关键字
14.5.6 同步阻塞
14.5.7 监视器概念
14.5.8 Volatile域
14.5.9 f?inal变量
14.5.10 原子性
14.5.11 死锁
14.5.12 线程局部变量
14.5.13 锁测试与超时
14.5.14 读/写锁
14.5.15 为什么弃用stop和suspend方法
14.6 阻塞队列
14.7 线程安全的集合
14.7.1 高效的映射、集和队列
14.7.2 映射条目的原子更新
14.7.3 对并发散列映射的批操作
14.7.4 并发集视图
14.7.5 写数组的拷贝
14.7.6 并行数组算法
14.7.7 较早的线程安全集合
14.8 Callable与Future
14.9 执行器
14.9.1 线程池
14.9.2 预定执行
14.9.3 控制任务组
14.9.4 Fork-Join框架
14.9.5 可完成Future
14.10 同步器
14.10.1 信号量
14.10.2 倒计时门栓
14.10.3 障栅
14.10.4 交换器
14.10.5 同步队列
14.11 线程与Swing
14.11.1 运行耗时的任务
14.11.2 使用Swing工作线程
14.11.3 单一线程规则
附录A Java关键字
第1章 Java程序设计概述
Java程序设计平台
Java发展简史
Java“白皮书”的关键术语 ▲
关于Java的常见误解
Java applet与Internet
1996年Java第一次发布就引起了人们的极大兴趣。关注Java的人士不仅限于计算机出版界,还有诸如《纽约时报》《华盛顿邮报》《商业周刊》这样的主流媒体。Java是第一种也是唯一一种在National Public Radio上占用了10分钟时间来进行介绍的程序设计语言,并且还得到了$100 000 000的风险投资基金。这些基金全部用来支持用这种特别的计算机语言开发的产品。重温那些令人兴奋的日子是很有意思的。本章将简要地介绍一下Java语言的发展历史。
1.1 Java程序设计平台
本书的第1版是这样描写Java的:“作为一种计算机语言,Java的广告词确实有点夸大其辞。然而,Java的确是一种优秀的程序设计语言。作为一个名副其实的程序设计人员,使用Java无疑是一个好的选择。有人认为:Java将有望成为一种最优秀的程序设计语言,但还需要一个相当长的发展时期。一旦一种语言应用于某个领域,与现存代码的相容性问题就摆在了人们的面前。”
我们的编辑手中有许多这样的广告词。这是Sun公司高层的某位不愿透露姓名的人士提供的(Sun是原先开发Java的公司)。Java有许多非常优秀的语言特性,本章稍后将会详细地讨论这些特性。由于相容性这个严峻的问题确实存在于现实中,所以,或多或少地还是有一些“累赘”被加到语言中,这就导致Java并不如想象中的那么完美无瑕。
但是,正像我们在第1版中已经指出的那样,Java并不只是一种语言。在此之前出现的那么多种语言也没有能够引起那么大的轰动。Java是一个完整的平台,有一个庞大的库,其中包含了很多可重用的代码和一个提供诸如安全性、跨操作系统的可移植性以及自动垃圾收集等服务的执行环境。
作为一名程序设计人员,常常希望能够有一种语言,它具有令人赏心悦目的语法和易于理解的语义(C++不是这样的)。与许多其他的优秀语言一样,Java完全满足了这些要求。有些语言提供了可移植性、垃圾收集等,但是,没有提供一个大型的库。如果想要有奇特的绘图功能、网络连接功能和数据库存取功能就必须自己动手编写代码。Java具备所有这些特性,它是一种功能齐全的出色语言,是一个高质量的执行环境,还提供了一个庞大的库。正是因为它集多种优势于一身,所以对广大的程序设计人员有着不可抗拒的吸引力。
1.2 Java“白皮书”的关键术语
Java的设计者已经编写了颇有影响力的“白皮书”,用来解释设计的初衷以及完成的情况,并且发布了一个简短的摘要。这个摘要用下面11个关键术语进行组织:
7)可移植性
2)面向对象
10)多线程
11)动态性
6)体系结构中立
本节将提供一个小结,给出白皮书中相关的说明,这是Java设计者对各个关键术语的论述,另外还会根据我们对Java当前版本的使用经验,给出对这些术语的理解。
注释:写这本书时,白皮书可以在www.oracle.com/technetwork/java/langenv-140151.html上找到。对于11个关键术语的论述请参看http://horstmann.com/corejava/java-an-overview/7Gosling.pdf。
1.2.1 简单性
人们希望构建一个无须深奥的专业训练就可以进行编程的系统,并且要符合当今的标准惯例。因此,尽管人们发现C++不太适用,但在设计Java的时候还是尽可能地接近C++,以便系统更易于理解。Java剔除了C++中许多很少使用、难以理解、易混淆的特性。在目前看来,这些特性带来的麻烦远远多于其带来的好处。
的确,Java语法是C++语法的一个“纯净”版本。这里没有头文件、指针运算(甚至指针语法)、结构、联合、操作符重载、虚基类等(请参阅本书各个章节给出的C++注释,其中比较详细地解释了Java与C++之间的区别)。然而,设计者并没有试图清除C++中所有不适当的特性。例如,switch语句的语法在Java中就没有改变。如果你了解C++就会发现可以轻而易举地转换到Java语法。
Java发布时,实际上C++并不是最常用的程序设计语言。很多开发人员都在使用Visual Basic和它的拖放式编程环境。这些开发人员并不觉得Java简单。很多年之后Java开发环境才迎头赶上。如今,Java开发环境已经远远超出大多数其他编程语言的开发环境。
简单的另一个方面是小。Java的目标之一是支持开发能够在小型机器上独立运行的软件。基本的解释器以及类支持大约仅为40KB;再加上基础的标准类库和对线程的支持(基本上是一个自包含的微内核)大约需要增加175KB。
在当时,这是一个了不起的成就。当然,由于不断的扩展,类库已经相当庞大了。现在有一个独立的具有较小类库的Java微型版(Java Micro Edition),这个版本适用于嵌入式设备。
1.2.2 面向对象
简单地讲,面向对象设计是一种程序设计技术。它将重点放在数据(即对象)和对象的接口上。用木匠打一个比方,一个“面向对象的”木匠始终关注的是所制作的椅子,第二位才是所使用的工具;一个“非面向对象的”木匠首先考虑的是所用的工具。在本质上,Java的面向对象能力与C++是一样的。
开发Java时面向对象技术已经相当成熟。Java的面向对象特性与C++旗鼓相当。Java与C++的主要不同点在于多重继承,在Java中,取而代之的是更简单的接口概念。与C++相比,Java提供了更丰富的运行时自省功能(有关这部分内容将在第5章中讨论)。
1.2.3 分布式
Java有一个丰富的例程库,用于处理像HTTP和FTP之类的TCP/IP协议。Java应用程序能够通过URL打开和访问网络上的对象,其便捷程度就好像访问本地文件一样。
如今,这一点已经得到认可,不过在1995年,主要还是从C++或Visual Basic程序连接Web服务器。
1.2.4 健壮性
Java的设计目标之一在于使得Java编写的程序具有多方面的可靠性。Java投入了大量的精力进行早期的问题检测、后期动态的(运行时)检测,并消除了容易出错的情况……Java和C++最大的不同在于Java采用的指针模型可以消除重写内存和损坏数据的可能性。
Java编译器能够检测许多在其他语言中仅在运行时才能够检测出来的问题。至于第二点,对于曾经花费几个小时来检查由于指针bug而引起内存冲突的人来说,一定很喜欢Java的这一特性。
1.2.5 安全性
Java适用于网络/分布式环境。为了达到这个目标,在安全方面投入了很大精力。使用Java可以构建防病毒、防篡改的系统。
从一开始,Java就设计成能够防范各种攻击,其中包括:
运行时堆栈溢出。如蠕虫和病毒常用的攻击手段。
破坏自己的进程空间之外的内存。
未经授权读写文件。
原先,Java对下载代码的态度是“尽管来吧!”。不可信代码在一个沙箱环境中执行,在这里它不会影响主系统。用户可以确信不会发生不好的事情,因为Java代码不论来自哪里,都不能脱离沙箱。
不过,Java的安全模型很复杂。Java开发包(Java Development Kit,JDK)的第一版发布之后不久,普林斯顿大学的一些安全专家就发现一些小bug会允许不可信的代码攻击主系统。
最初,安全bug可以快速修复。遗憾的是,经过一段时间之后,黑客已经很擅长找出安全体系结构实现中的小漏洞。Sun以及之后的Oracle为修复bug度过了一段很是艰难的日子。
遭遇多次高调攻击之后,浏览器开发商和Oracle都越来越谨慎。Java浏览器插件不再信任远程代码,除非代码有数字签名而且用户同意执行这个代码。
注释:现在看来,尽管Java安全模型没有原先预想的那么成功,但Java在那个时代确实相当超前。微软提供了一种与之竞争的代码传输机制,其安全性完全依赖于数字签名。显然这是不够的,因为微软自身产品的任何用户都可以证实,知名开发商的程序确实会崩溃并对系统产生危害。
1.2.6 体系结构中立
编译器生成一个体系结构中立的目标文件格式,这是一种编译过的代码,只要有Java运行时系统,这些编译后的代码可以在许多处理器上运行。Java编译器通过生成与特定的计算机体系结构无关的字节码指令来实现这一特性。精心设计的字节码不仅可以很容易地在任何机器上解释执行,而且还可以动态地翻译成本地机器代码。
当时,为“虚拟机”生成代码并不是一个新思路。诸如Lisp、Smalltalk和Pascal等编程语言多年前就已经采用了这种技术。
当然,解释虚拟机指令肯定会比全速运行机器指令慢很多。然而,虚拟机有一个选项,可以将执行最频繁的字节码序列翻译成机器码,这一过程被称为即时编译。
Java虚拟机还有一些其他的优点。它可以检测指令序列的行为,从而增强其安全性。
1.2.7 可移植性
与C和C++不同,Java规范中没有“依赖具体实现”的地方。基本数据类型的大小以及有关运算都做了明确的说明。
例如,Java中的int永远为32位的整数,而在C/C++中,int可能是16位整数、32位整数,也可能是编译器提供商指定的其他大小。唯一的限制只是int类型的大小不能低于short int,并且不能高于long int。在Java中,数据类型具有固定的大小,这消除了代码移植时令人头痛的主要问题。二进制数据以固定的格式进行存储和传输,消除了字节顺序的困扰。字符串是用标准的Unicode格式存储的。
作为系统组成部分的类库,定义了可移植的接口。例如,有一个抽象的Window类,并给出了在UNIX、Windows和Macintosh环境下的不同实现。
选择Window类作为例子可能并不太合适。凡是尝试过的人都知道,要编写一个在Windows、Macintosh和10种不同风格的UNIX上看起来都不错的程序有多么困难。Java 1.0就尝试着做了这么一个壮举,发布了一个将常用的用户界面元素映射到不同平台上的简单工具包。遗憾的是,花费了大量的心血,却构建了一个在各个平台上都难以让人接受的库。原先的用户界面工具包已经重写,而且后来又再次重写,不过跨平台的可移植性仍然是个问题。
不过,除了与用户界面有关的部分外,所有其他Java库都能很好地支持平台独立性。你可以处理文件、正则表达式、XML、日期和时间、数据库、网络连接、线程等,而不用操心底层操作系统。不仅程序是可移植的,Java API往往也比原生API质量更高。
1.2.8 解释型
Java解释器可以在任何移植了解释器的机器上执行Java字节码。由于链接是一个增量式且轻量级的过程,所以,开发过程也变得更加快捷,更加具有探索性。
这看上去很不错。用过Lisp、Smalltalk、Visual Basic、Python、R或Scala的人都知道“快捷而且具有探索性”的开发过程是怎样的。你可以做些尝试,然后就能立即看到结果。Java开发环境并没有将重点放在这种体验上。
1.2.9 高性能
尽管对解释后的字节码性能已经比较满意,但在有些场合下还需要更加高效的性能。字节码可以(在运行时刻)动态地翻译成对应运行这个应用的特定CPU的机器码。
使用Java的头几年,许多用户不同意这样的看法:性能就是“适用性更强”。然而,现在的即时编译器已经非常出色,以至于成了传统编译器的竞争对手。在某些情况下,甚至超越了传统编译器,原因是它们含有更多的可用信息。例如,即时编译器可以监控经常执行哪些代码并优化这些代码以提高速度。更为复杂的优化是消除函数调用(即“内联”)。即时编译器知道哪些类已经加载。基于当前加载的类集,如果特定的函数不会被覆盖,就可以使用内联。必要时,还可以撤销优化。
1.2.10 多线程
多线程可以带来更好的交互响应和实时行为。
如今,我们非常关注并发性,因为摩尔定律行将完结。我们不再追求更快的处理器,而是着眼于获得更多的处理器,而且要让它们一直保持工作。不过,可以看到,大多数编程语言对于这个问题并没有显示出足够的重视。
Java在当时很超前。它是第一个支持并发程序设计的主流语言。从白皮书中可以看到,它的出发点稍有些不同。当时,多核处理器还很神秘,而Web编程才刚刚起步,处理器要花很长时间等待服务器响应,需要并发程序设计来确保用户界面不会“冻住”。
并发程序设计绝非易事,不过Java在这方面表现很出色,可以很好地管理这个工作。
1.2.11 动态性
从各种角度看,Java与C或C++相比更加具有动态性。它能够适应不断发展的环境。库中可以自由地添加新方法和实例变量,而对客户端却没有任何影响。在Java中找出运行时类型信息十分简单。
当需要将某些代码添加到正在运行的程序中时,动态性将是一个非常重要的特性。一个很好的例子是:从Internet下载代码,然后在浏览器上运行。如果使用C或C++,这确实难度很大,不过Java设计者很清楚动态语言可以很容易地实现运行程序的演进。最终,他们将这一特性引入这个主流程序设计语言中。
注释:Java成功地推出后不久,微软就发布了一个叫做J++的产品,它与Java有几乎相同的编程语言以及虚拟机。现在,微软不再支持J++,取而代之的是另一种名为C#的语言。C#与Java有很多相似之处,然而使用的却是完全不同的虚拟机。本书不准备介绍J++或C#语言。
1.3 Java applet与Internet
这里的想法很简单:用户从Internet下载Java字节码,并在自己的机器上运行。在网页中运行的Java程序称为applet。要使用applet,需要启用Java的Web浏览器执行字节码。不需要安装任何软件。任何时候只要访问包含applet的网页都会得到程序的最新版本。最重要的是,要感谢虚拟机的安全性,它让我们不必再担心来自恶意代码的攻击。
在网页中插入一个applet就如同在网页中嵌入一幅图片。applet会成为页面的一部分。文本环绕着applet所占据的空间周围。关键的一点是这个图片是活动的。它可以对用户命令做出响应,改变外观,在运行它的计算机与提供它的计算机之间传递数据。
图1-1展示了一个很好的动态网页的例子。Jmol applet显示了分子结构,这将需要相当复杂的计算。在这个网页中,可以利用鼠标进行旋转,调整焦距等操作,以便更好地理解分子结构。用静态网页就无法实现这种直接的操作,而applet却可以达到此目的(可以在http://jmol.sourceforge.net上找到这个applet)。
图1-1 Jmol applet
当applet首次出现时,人们欣喜若狂。许多人相信applet的魅力将会导致Java迅速地流行起来。然而,初期的兴奋很快就淡化了。不同版本的Netscape与Internet Explorer运行不同版本的Java,其中有些早已过时。这种糟糕的情况导致更加难于利用Java的最新版本开发applet。实际上,为了在浏览器中得到动态效果,Adobe的Flash技术变得相当流行。后来,Java遭遇了严重的安全问题,浏览器和Java浏览器插件变得限制越来越多。如今,要在浏览器中使用applet,这不仅需要一定的水平,而且要付出努力。例如,如果访问Jmol网站,可能会看到一个消息,警告你要适当地配置浏览器允许运行applet。
1.4 Java发展简史
本节将介绍Java的发展简史。这些内容来自很多出版资料(最重要的是SunWorld的在线杂志1995年7月刊上对Java创建者的专访)。
Java的历史要追溯到1991年,由Patrick Naughton和James Gosling(一个全能的计算机奇才)带领的Sun公司的工程师小组想要设计一种小型的计算机语言,主要用于像有线电视转换盒这类的消费设备。由于这些消费设备的处理能力和内存都很有限,所以语言必须非常小且能够生成非常紧凑的代码。另外,由于不同的厂商会选择不同的中央处理器(CPU),因此这种语言的关键是不与任何特定的体系结构捆绑在一起。这个项目被命名为“Green”。
代码短小、紧凑且与平台无关,这些要求促使开发团队设计一个可移植的语言,可以为虚拟机生成中间代码。
不过,Sun公司的人都有UNIX的应用背景。因此,所开发的语言以C++为基础,而不是Lisp、Smalltalk或Pascal。不过,就像Gosling在专访中谈到的:“毕竟,语言只是实现目标的工具,而不是目标本身”。Gosling把这种语言称为“Oak”(这么起名的原因大概是因为他非常喜欢自己办公室外的橡树)。Sun公司的人后来发现Oak是一种已有的计算机语言的名字,于是,将其改名为Java。事实证明这是一个很有灵感的选择。
1992年,Green项目发布了它的第一个产品,称之为“*7”。这个产品具有非常智能的远程控制。遗憾的是,Sun公司对生产这个产品并不感兴趣,Green项目组的人员必须找出其他的方法来将他们的技术推向市场。然而,没有一个标准消费品电子公司对此感兴趣。于是,Green项目组竞标了一个提供视频点播等新型服务的有线电视盒的项目,但没有成功(有趣的是,得到这个项目的公司的领导恰恰是开创Netscape公司的Jim Clark。Netscape公司后来对Java的成功给予了很大的帮助)。
Green项目(这时换了一个新名字——“First Person公司”)花费了1993年一整年以及1994年的上半年,一直在苦苦寻求其技术的买家。然而,一个也没有找到(Patrick Naughton,项目组的创立人之一,也是完成此项目大多数市场工作的人,声称为了销售这项技术,累计飞行了300 000英里)。1994年First Person公司解散了。
当这一切在Sun公司发生的时候,Internet的万维网也在日渐发展壮大。万维网的关键是把超文本页面转换到屏幕上的浏览器。1994年大多数人都在使用Mosaic,这是一个1993年出自伊利诺斯大学超级计算中心的非商业化的Web浏览器(Mosaic的一部分是由Marc Andreessen编写的。当时,他作为一名参加半工半读项目的本科生,编写了这个软件,每小时的薪水只有6.85美元。他后来成了Netscape公司的创始人之一和技术总监,可谓名利双收)。
在接受SunWorld采访的时候,Gosling说在1994年中期,Java语言的开发者意识到:“我们能够建立一个相当酷的浏览器。我们已经拥有在客户机/服务器主流模型中所需要的体系结构中立、实时、可靠、安全——这些在工作站环境并不太重要,所以,我们决定开发浏览器。”
实际的浏览器是由Patrick Naughton和Jonathan Payne开发的,并演变为HotJava浏览器。为了炫耀Java语言超强的能力,HotJava浏览器采用Java编写。设计者让HotJava浏览器具有在网页中执行内嵌代码的能力。这一“技术印证”在日的SunWorld上得到展示,同时引发了人们延续至今的对Java的狂热追逐。
1996年年初,Sun发布了Java的第1个版本。人们很快地意识到Java1.0不能用来进行真正的应用开发。的确,可以使用Java 1.0来实现在画布上随机跳动的神经质的文本applet,但它却没有提供打印功能。坦率地说,Java 1.0的确没有为其黄金时期的到来做好准备。后来的Java 1.1弥补了其中的大多明显的缺陷,大大改进了反射能力,并为GUI编程增加了新的事件处理模型。不过它仍然具有很大的局限性。
1998年JavaOne会议的头号新闻是即将发布Java 1.2版。这个版本取代了早期玩具式的GUI,并且它的图形工具箱更加精细而具有可伸缩性,更加接近“一次编写,随处运行”的承诺。在1998年12月Java 1.2发布三天之后,Sun公司市场部将其名称改为更加吸引人的“Java 2标准版软件开发工具箱1.2版”。
除了“标准版”之外,Sun还推出了两个其他的版本:一个是用于手机等嵌入式设备的“微型版”;另一个是用于服务器端处理的“企业版”。本书主要讲述标准版。
标准版的1.3和1.4版本对最初的Java 2版本做出了某些改进,扩展了标准类库,提高系统性能。当然,还修正了一些bug。在此期间,Java applet采用低调姿态,并淡化了客户端的应用,但Java却成为服务器端应用的首选平台。
5.0版是自1.1版以来第一个对Java语言做出重大改进的版本(这一版本原来被命名为1.5版,在2004年的JavaOne会议之后,版本数字升至5.0)。经历了多年的研究,这个版本添加了泛型类型(generic type)(类似于C++的模板),其挑战性在于添加这一特性并没有对虚拟机做出任何修改。另外,还有几个受C#启发的很有用的语言特性:“for each”循环、自动装箱和注解。
版本6(没有后缀.0)于2006年年末发布。同样,这个版本没有对语言方面再进行改进。但是,改进了其他性能,并增强了类库。
随着数据中心越来越依赖于商业硬件而不是专用服务器,Sun Microsystems终于沦陷,于2009年被Oracle收购。Java的开发停滞了很长一段时间。直到2011年Oracle发布了Java的一个新版本,Java 7,其中只做了一些简单的改进。
2014年,Java 8终于发布,在近20年中这个版本有了最大的改变。Java 8提供了一种“函数式”编程方式,可以很容易地表述并发执行的计算。所有编程语言都必须与时俱进,Java在这方面显示出非凡的能力。
表1-1展示了Java语言以及类库的发展状况。可以看到,应用程序编程接口(API)的规模发生了惊人的变化。
表1-1 Java语言的发展状况
版  本 年  份 语言新特性 类与接口的数量
1.0 1996 语言本身 211
1.1 1997 内部类 477
1.2 1998 strictfp修饰符 1524
1.3 2000 无 1840
1.4 2002 断言 2723
5.0 2004 泛型类、“for each”循环、可变元参数、自动装箱、元数据、枚举、静态导入 3279
6 2006 无 3793
7 2011 基于字符串的switch、钻石操作符、二进制字面量、异常处理改进 4024
8 2014 lambda表达式,包含默认方法的接口,流和日期/时间库 4240
1.5 关于Java的常见误解
在结束本章之前,我们列出了一些关于Java的常见误解,同时给出了解释。
1.?Java是HTML的扩展
Java是一种程序设计语言;HTML是一种描述网页结构的方式。除了用于在网页上放置Java applet的HTML扩展之外,两者没有任何共同之处。
2.?使用XML,所以不需要Java
Java是一种程序设计语言;XML是一种描述数据的方式。可以使用任何一种程序设计语言处理XML数据,而Java API对XML处理提供了很好的支持。此外,许多重要的第三方XML工具采用Java编写。有关这方面更加详细的信息请参看卷Ⅱ。
3.?Java是一种非常容易学习的程序设计语言
像Java这种功能强大的语言大都不太容易学习。首先,必须将编写玩具式程序的轻松和开发实际项目的艰难区分开来。需要注意的是:本书只用了7章讨论Java语言。在两卷中,其他的章节介绍如何使用Java类库将Java语言应用到实际中去。Java类库包含了数千种类和接口以及数万个函数。幸运的是,并不需要知道它们中的每一个,然而,要想Java解决实际问题,还是需要了解不少内容的。
4.?Java将成为适用于所有平台的通用性编程语言
从理论上讲,这是完全有可能的。但在实际中,某些领域其他语言有更出色的表现,比如,Objective C和后来的Swift在iOS设备上就有着无可取代的地位。浏览器中的处理几乎完全由JavaScript掌控。Windows程序通常都用C++或C#编写。Java在服务器端编程和跨平台客户端应用领域则很有优势。
5.?Java只不过是另外一种程序设计语言
Java是一种很好的程序设计语言,很多程序设计人员喜欢Java胜过C、C++或C#。有上百种好的程序设计语言没有广泛地流行,而带有明显缺陷的语言,如:C++和Visual Basic却大行其道。
这是为什么呢?程序设计语言的成功更多地取决于其支撑系统的能力,而不是优美的语法。人们主要关注:是否提供了易于实现某些功能的易用、便捷和标准的库?是否有开发工具提供商能建立强大的编程和调试环境?语言和工具集是否能够与其他计算基础架构整合在一起?Java的成功源于其类库能够让人们轻松地完成原本有一定难度的事情。例如:联网Web应用和并发。Java减少了指针错误,这是一个额外的好处,因此使用Java编程的效率更高。但这些并不是Java成功的全部原因。
6.?Java是专用的,应该避免使用
最初创建Java时,Sun为销售者和最终用户提供了免费许可。尽管Sun对Java拥有最终的控制权,不过在语言版本的不断发展和新库的设计过程中还涉及很多其他公司。虚拟机和类库的源代码可以免费获得,不过仅限于查看,而不能修改和再发布。Java是“闭源的,不过可以很好地使用”。
这种状况在2007年发生了戏剧性的变化,Sun声称Java未来的版本将在General Public License(GPL)下提供。Linux使用的是同一个开放源代码许可。Oracle一直致力于保持Java开源。只有一点美中不足——专利。根据GPL,任何人都可以得到专利许可,允许其使用和修改Java,不过仅限于桌面和服务器平台。如果你想在嵌入式系统中使用Java,就需要另外一个不同的许可,这很可能需要付费。不过,这些专利在未来十年就会到期,那时Java就完全免费了。
7.?Java是解释型的,因此对于关键的应用程序速度太慢了
早期的Java是解释型的。现在Java虚拟机使用了即时编译器,因此采用Java编写的“热点”代码其运行速度与C++相差无几,有些情况下甚至更快。
对于Java桌面应用速度慢,人们已经抱怨很多年了。但是,今天的计算机速度远比人们发出抱怨的时候快了很多。一个较慢的Java程序与几年前相当快的C++程序相比还要快一些。
8.?所有的Java程序都是在网页中运行的
所有的Java applet都是在网页浏览器中运行的。这也恰恰是applet的定义,即一种在浏览器中运行的Java程序。然而,大多数Java程序是运行在Web浏览器之外的独立应用程序。实际上,很多Java程序都在Web服务器上运行并生成用于网页的代码。
9.?Java程序是主要的安全风险
对于早期的Java,有过关于安全系统失效的报道,曾经一度引起公众哗然。研究人员将这视为一种挑战,即努力找出Java的漏洞,对applet安全模型的强度和复杂度发起挑战。随后,人们很快就解决了引发问题的所有技术因素。后来又发现了更严重的漏洞,而Sun以及后来的Oracle反应却过于迟缓。浏览器制造商则有些反应过度,他们甚至默认禁用了Java。客观地来讲,可以想想针对Windows可执行文件和Word宏有数百万种病毒攻击,并造成了巨大的损害,不过奇怪的是却很少有人批评被攻击平台的脆弱。
有些系统管理员甚至在公司浏览器中禁用了Java,而同时却允许用户下载可执行文件和Word文档,实际上,这些带来的风险远甚于使用Java。尽管距离Java诞生已经20年之久,与其他常用的执行平台相比,Java还是安全得多。
10.?JavaScript是Java的简易版
JavaScript是一种在网页中使用的脚本语言,它是由Netscape发明的,原来的名字叫做LiveScript。JavaScript的语法类似Java,除此之外,两者无任何关系。当然,名字有些相像。JavaScript的一个子集已经标准化为ECMA-262。与Java applet相比,JavaScript更紧密地与浏览器集成在一起。特别是JavaScript程序可以修改正在显示的文档,而applet只能在有限的区域内控制外观。
11.?使用Java可以用廉价的Internet设备取代桌面计算机
当Java刚刚发布的时候,一些人打赌:肯定会有这样的好事情发生。一些公司已经生产出Java网络计算机的原型,不过用户还不打算放弃功能强大而便利的桌面计算机,而去使用没有本地存储而且功能有限的网络设备。当然,如今世界已经发生改变,对于大多数最终用户,常用的平台往往是手机或平板电脑。这些设备大多使用安卓平台,这是Java的衍生产物。学习Java编程肯定也对Android编程很有帮助。
第2章 Java程序设计环境
▲ 安装Java开发工具包 ▲ 运行图形化应用程序
▲ 使用命令行工具
▲ 构建并运行applet
▲ 使用集成开发环境
本章主要介绍如何安装Java开发工具包(JDK)以及如何编译和运行不同类型的程序:控制台程序、图形化应用程序以及applet。运行JDK工具的方法是在终端窗口中键入命令。然而,很多程序员更喜欢使用集成开发环境。为此,将在稍后介绍如何使用免费的开发环境编译和运行Java程序。尽管学起来很容易,但集成开发环境需要吞噬大量资源,编写小型程序时也比较烦琐。一旦掌握了本章的技术,并选定了自己的开发工具,就可以学习第3章,开始研究Java程序设计语言。
2.1 安装Java开发工具包
Oracle公司为Linux、Mac OS X、Solaris和Windows提供了Java开发工具包(JDK)的最新、最完整的版本。用于很多其他平台的版本仍处于多种不同的开发状态中,不过,这些版本都由相应平台的开发商授权并分发。
2.1.1 下载JDK
要想下载Java开发工具包,可以访问Oracle网站:www.oracle.com/technetwork/java/javase/downloads,在得到所需的软件之前必须弄清楚大量专业术语。请看表2-1的总结。
表2-1 Java术语
术 语 名 缩写 解  释
Java Development Kit JDK 编写Java程序的程序员使用的软件
Java Runtime Environment JRE 运行Java程序的用户使用的软件
Server JRE — 在服务器上运行Java程序的软件
Standard Edition SE 用于桌面或简单服务器应用的Java平台
Enterprise Edition
EE 用于复杂服务器应用的Java平台
Micro Edition ME 用于手机和其他小型设备的Java平台
Java FX — 用于图形化用户界面的一个替代工具包,在Oracle的Java SE发布版本中提供
OpenJDK — Java SE的一个免费开源实现,不包含浏览器集成或JavaFX
Java 2 J2 一个过时的术语,用于描述1998年~2006年之间的Java版本
Software Development Kit SDK 一个过时的术语,用于描述1998年~2006年之间的JDK
Update u Oracle的术语,表示bug修正版本
NetBeans — Oracle的集成开发环境
你已经看到,JDK是Java Development Kit的缩写。有点混乱的是:这个工具包的版本1.2~版本1.4被称为Java SDK(软件开发包,Software Development Kit)。在某些场合下,还可以看到这个过时的术语。另外,还有一个术语是Java运行时环境(JRE),它包含虚拟机但不包含编译器。这并不是开发者想要的环境,而是专门为不需要编译器的用户而提供。
接下来,Java SE会大量出现,相对于Java EE(Enterprise Edition)和Java ME(Micro Edition),它是Java的标准版。
Java 2这种提法始于1998年。当时Sun公司的销售人员感觉增加小数点后面的数值改变版本号并没有反映出JDK 1.2的重大改进。但是,由于在发布之后才意识到这个问题,所以决定开发工具包的版本号仍然沿用1.2,接下来的版本是1.3、1.4和5.0。但是,Java平台被重新命名为Java 2。因此,就有了Java 2 Standard Edition Software Development Kit(Java 2标准版软件开发包)的5.0版,即J2SE SDK 5.0。
幸运的是,2006年版本号得到简化。Java标准版的下一个版本取名为Java SE 6,后来又有了Java SE 7和Java SE 8。不过,“内部”版本号分别是1.6.0、1.7.0和1.8.0。
当Oracle为解决一些紧急问题做出某些微小的版本改变时,将其称为更新。例如:Java SE 8u31是Java SE 8的第31次更新,它的内部版本号是1.8.0_31。更新不需要安装在前一个版本上,它会包含整个JDK的最新版本。另外,并不是所有更新都公开发布,所以如果“更新31”之后没有“更新32”,你也不用惊慌。
对于Windows或Linux,需要在x86(32位)和x64(64位)版本之间做出选择。应当选择与你的操作系统体系结构匹配的版本。
对于Linux,还可以在RPM文件和.tar.gz文件之间做出选择。我们建议使用后者,可以在你希望的任何位置直接解压缩这个压缩包。
现在你已经了解了如何选择适当的JDK。下面做一个小结:
你需要的是JDK(Java SE开发包),而不是JRE。
Windows或Linux:32位选择x86,64位以x64。
Linux:选择.tar.gz版本。
接受许可协议,然后下载文件。
注释:Oracle提供了一个捆绑包,其中包含Java开发包(JDK)和NetBeans集成开发环境。建议现在不要安装任何捆绑包,而只需安装Java开发包。如果以后你打算使用NetBeans,可以再从http://netbeans.org下载。
2.1.2 设置JDK
下载JDK之后,需要安装这个开发包并明确要在哪里安装,后面还会需要这个信息。
在Windows上,启动安装程序。会询问你要在哪里安装JDK。最好不要接受路径名中包含空格的默认位置,如c:\Program Files\Java\jdk1.8.0_version。取出路径名中的Program Files部分就可以了。
在Mac上,运行安装程序。这会把软件安装到/Library/Java/JavaVirtualMachines/jdk1.8.0_version.jdk/Contents/Home。用Finder找到这个目录。
在Linux上,只需要把.tar.gz文件解压缩到你选择的某个位置,如你的主目录,或者/opt。如果从RPM文件安装,则要反复检查是否安装在/usr/java/jdk1.8.0_version。
在这本书中,安装目录用jdk表示。例如,谈到jdk/bin目录时,是指/opt/jdk1.8.0_31/bin或c:\Java\jdk1.8.0_31\bin目录。
在Windows或Linux上安装JDK时,还需要另外完成一个步骤:将jdk/bin目录增加到执行路径中——执行路径是操作系统查找可执行文件时所遍历的目录列表。
在Linux上,需要在?/.bashrc或?/.bash_prof?ile文件的最后增加这样一行:
一定要使用JDK的正确路径,如/opt/jdk1.8.0_31。
在Windows上,启动控制面板,选择“系统与安全”(System and Security),再选择“系统”(System),选择高级系统设置(Advanced System Settings)(参见图2-1)。在系统属性(System Properties)对话框中,点击“高级”(Advanced)标签页,然后点击“环境”(Environment)按钮。
图2-1 Windows 7中设置系统属性
滚动“系统变量”(System Variables)列表,直到找到名为Path的变量。点击“编辑”(Edit)按钮(参见图2-2)。将jdk\bin目录增加到路径最前面,并用一个分号分隔新增的这一项,如下所示:
图2-2 Windows 7中设置Path环境变量
注意要把jdk替换为具体的Java安装路径,如c:\Java\jdk1.8.0_31。如果忽视前面的建议,想要保留Program Files部分,则要把整个路径用双引号引起来:"c:\Program Files\Java\jdk1.8.0_31\bin";其他目录。
保存所做的设置。之后新打开的所有控制台窗口都会有正确的路径。
可以如下测试设置是否正确:打开一个终端窗口,键入:
然后按回车键。应该能看到显示以下信息:
如果得到诸如“javac: command not found”(javac::命令未找到)或“The name specif?ied is not recognized as an internal or external command, operable program or batch f?ile”(指定名不是一个内部或外部命令、可执行的程序或批文件),就需要退回去反复检查你的安装。
2.1.3 安装库源文件和文档
库源文件在JDK中以一个压缩文件src.zip的形式发布,必须将其解压缩后才能够访问源代码。建议按照下面所述的步骤进行操作。很简单:
1)确保JDK已经安装,并且jdk/bin目录在执行路径中。
2)在主目录中建立一个目录javasrc。如果愿意,可以在一个终端窗口完成这个步骤。
3)在jdk目录下找到文件src.zip。
4)将src.zip文件解压缩到javasrc目录。在一个终端窗口中,可以执行以下命令:
提示:src.zip文件中包含了所有公共类库的源代码。要想获得更多的源代码(例如:编译器、虚拟机、本地方法以及私有辅助类),请访问网站:http://jdk8.java.net。
文档包含在一个压缩文件中,它是一个独立于JDK的压缩文件。可以直接从网站http://www.oracle.com/technetwork/java/javase/downloads下载这个文档。操作步骤如下:
1)下载文档压缩文件。这个文件名为jdk-version-docs-all.zip,其中的version表示版本号,例如8u31。
2)解压缩这个文件,将doc目录重命名为一个更有描述性的名字,如javadoc。如果愿意,可以从命令行完成这个工作:
这里version是相应的版本号。
3)在浏览器中导航到javadoc/api/index.html,将这个页面增加到书签。
还要安装本书的程序示例。可以从http://horstmann.com/corejava下载示例。这些程序打包在一个zip文件corejava.zip中。可以将程序解压缩到你的主目录。它们会放在目录corejava中。如果愿意,可以从命令行完成这个工作:
2.2 使用命令行工具
如果在此之前有过使用Microsoft Visual Studio等开发环境编程的经验,你可能会习惯于有一个内置文本编辑器、用于编译和启动程序的菜单以及调试工具的系统。JDK完全没有这些功能。所有工作都要在终端窗口中键入命令来完成。这听起来很麻烦,不过确实是一个基本技能。第一次安装Java时,你可能希望在安装开发环境之前先检查Java的安装是否正确。另外,通过自己执行基本步骤,你可以更好地理解开发环境的后台工作。
不过,掌握了编译和运行Java程序的基本步骤之后,你可能就会希望使用专业的开发环境。下一节会介绍如何使用开发环境。
首先介绍较难的方法:从命令行编译并运行Java程序。
1)打开一个终端窗口。
2)进入corejava/v1ch02/Welcome目录(CoreJava是安装本书示例源代码的目录,请参看2.1.3节)。
3)键入下面的命令:
然后,将会在终端窗口中看到图2-3所示的输出。
图2-3 编译并运行Welcome.java
祝贺你!你已经编译并运行了第一个Java程序。
那么,刚才都进行了哪些操作呢?javac程序是一个Java编译器。它将文件Welcome.java编译成Welcome.class。java程序启动Java虚拟机。虚拟机执行编译器放在class文件中的字节码。
Welcome程序非常简单。它只是向控制台输出了一条消息。你可能想查看程序清单2-1的程序代码。(在下一章中,将解释它是如何工作的。)
程序清单2-1 Welcome/Welcome.java
在使用可视化开发环境的年代,许多程序员对于在终端窗口中运行程序已经很生疏了。常常会出现很多错误,最终导致令人沮丧的结果。
一定要注意以下几点:
如果手工输入源程序,一定要注意大小写。尤其是类名为Welcome,而不是welcome或WELCOME。
编译器需要一个文件名(Welcome.java),而运行程序时,只需要指定类名(Welcome),不要带扩展名.java或.class。
如果看到诸如Bad command or f?ile name或javac:command not found这类消息,就要返回去反复检查安装是否有问题,特别是执行路径的设置。
如果javac报告了一个错误,指出无法找到Welcome.java,就应该检查目录中是否存在这个文件。
在Linux环境下,检查Welcome.java是否以正确的大写字母开头。
在Windows环境下,使用命令dir,而不要使用图形浏览器工具。有些文本编辑器(特别是Notepad)在每个文件名后面要添加扩展名.txt。如果使用Notepad编辑Welcome.java就会存为Welcome.java.txt。对于默认的Windows设置,浏览器与Notepad都隐含.txt扩展名,这是因为这个扩展名属于“已知的文件类型”。此时,需要重新命名这个文件,使用命令ren,或是另存一次,为文件名加一对双引号,如:“Welcome.java”。
如果运行程序之后,收到关于java.lang.NoClassDefFoundError的错误消息,就应该仔细地检查出问题的类的名字。
如果收到关于welcome(w为小写)的错误消息,就应该重新执行命令:java Welcome(W为大写)。记住,Java区分大小写。
如果收到有关Welcome/java的错误信息,这说明你错误地键入了java Welcome.java,应该重新执行命令java Welcome。
如果键入java Welcome,而虚拟机没有找到Welcome类,就应该检查一下是否有人设置了系统的CLASSPATH环境变量(将这个变量设置为全局并不是一个提倡的做法,然而,Windows中有些比较差的软件安装程序就是这样做的)。可以像设置PATH环境变量一样设置CLASSPATH,不过这里将删除这个设置。
提示:在http://docs.oracle.com/javase/tutorial/getStarted/cupojava/上有一个很好的教程。其中提到了初学者经常容易犯的一些错误。
2.3 使用集成开发环境
上一节中,你已经了解了如何从命令行编译和运行一个Java程序。这是一个很有用的技能,不过对于大多数日常工作来说,都应当使用集成开发环境。这些环境非常强大,也很方便,不使用这些环境有些不合情理。我们可以免费得到一些很棒的开发环境,如Eclipse、NetBeans和IntelliJ IDEA程序。这一章中,我们将学习如何从Eclipse起步。当然,如果你喜欢其他开发环境,学习本书时也完全可以使用你喜欢的环境。
本节将介绍如何使用Eclipse编译一个程序。Eclipse是一个可以从网站http://eclipse.org/downloads上免费下载得到的集成开发环境。Eclipse已经有面向Linux、Mac OS X、Solaris和Windows的版本。访问下载网站时,选择“Eclipse IDE for Java Developers”。再根据你的操作系统选择32位或64位版本。
将Eclipse解压缩到你选择的位置,执行这个zip文件中的eclipse程序。
下面是用Eclipse编写程序的一般步骤。
1)启动Eclipse之后,从菜单选择File→ New→Project。
2)从向导对话框中选择Java Project(如图2-4所示)。
3)点击Next按钮,不选中“Use default location”复选框。点击Browse导航到corejava/v1ch02/Welcome目录(见图2-5)。
图2-5 配置Eclipse工程
4)点击Finish按钮。这个工程已经创建完成了。
5)点击工程窗口左边窗格中的三角,直到找到Welcome.java并双击。现在应该看到带有程序代码的窗口了(如图2-6所示)。
图2-6 使用Eclipse编辑源文件
6)用鼠标右键点击最左侧窗格中的工程名(Welcome),选择Run→Run As→Java Application。程序输出会显示在控制台窗格中。
可以假定,这个程序没有输入错误或bug(毕竟,这段代码只有几行)。为了说明问题,假定在代码中不小心出现了录入错误(或者甚至语法错误)。试着将原来的程序修改一下,让它包含一些录入错误,例如,将String的大小写弄错:
注意string下面的波折线。点击源代码下标签页中的Problems,展开小三角,会看到一个错误消息,指出有一个未知的string类型(见图2-7)。点击这个错误消息。光标会移到编辑窗口中相应的代码行,可以在这里纠正错误。利用这个特性可以快速地修正错误。
提示:通常,Eclipse错误报告会伴有一个灯泡图标。点击这个图标可以得到一个建议解决这个错误的方案列表。
图2-7 Eclipse中的错误消息
2.4 运行图形化应用程序
Welcome程序并不会引起人们的兴奋。接下来,给出一个图形化应用程序。这个程序是一个简单的图像文件查看器(viewer),它可以加载并显示一个图像。首先,由命令行编译并运行这个程序。
1)打开一个终端窗口。
2)进入corejava/v1ch02/ImageViewer。
将弹出一个标题栏为ImageViewer的新程序窗口(如图2-8所示)。
现在,选择File→Open,然后找到一个图像文件并打开它(我们在同一个目录下提供了两个示例文件)。要关闭这一程序,只需要点击标题栏中的关闭按钮或者从菜单中选择File→Exit。
下面快速地浏览一下源代码(程序清单2-2)。这个程序比第一个程序要长很多,但是只要想一想用C或C++编写同样功能的应用程序所需要的代码量,就不会觉得它太复杂了。本书将在第10章~第12章介绍如何编写像这样的图形化应用程序。
程序清单2-2 ImageViewer/ImageViewer.java
2.5 构建并运行applet
本书给出的前两个程序是Java应用程序。它们与所有本地程序一样,是独立的程序。然而,正如第1章提到的,有关Java的大量宣传都在炫耀Java在浏览器中运行applet的能力。如果你对“过去的记忆”感兴趣,可以继续阅读下面的内容来了解如何构建和运行一个applet,以及如何在Web浏览器中显示;如果你不感兴趣,完全可以跳过这个例子,直接转到第3章。
首先,打开终端窗口并转到CoreJava/v1ch02/RoadApplet,然后,输入下面的命令:
图2-9显示了在applet查看器窗口中显示的内容。这个applet图示显示了司机随意减速可能导致交通拥堵的情况。1996年,applet是创建这种可视化显示的绝佳工具。
第一条命令是大家已经非常熟悉的调用Java编译器的命令。它将RoadApplet.java源文件编译成字节码文件RoadApplet.class。
不过这一次不要运行java程序。首先,使用jar工具将类文件打包到一个“JAR文件”。然后调用appletviewer程序,这是JDK自带的一个工具,可以用来快速测试applet。需要为这个程序指定一个HTML文件名,而不是一个Java类文件名。RoadApplet.html文件的内容如本节最后的程序清单2-3所示。
程序清单2-3 RoadApplet/RoadApplet.html
如果熟悉HTML,你会注意这里的标准HTML标记和applet标签,这会告诉applet查看器加载applet,其代码存储在RoadApplet.jar中。applet会忽略除applet标签外的所有HTML标签。
当然,applet要在浏览器中查看。遗憾的是,现在很多浏览器并不提供Java支持,或者启用Java很困难。对此,最好使用Firefox。
如果使用Windows或Mac OS X,Firefox会自动启用计算机上安装的Java。在Linux上,则需要用下面的命令启用这个插件:
作为检查,可以在地址栏键入about:plugins,查找Java插件。确保使用这个插件的Java SE 8版本,为此要查找MIME类型application/x-java-version=1.8。
接下来,将浏览器导航到http://horstmann.com/applets/RoadApplet/RoadApplet.html,对所有安全提示都选择接受,保证最后会显示applet。
遗憾的是,只是测试刚刚编译的applet还不够。horstmann.com服务器上的applet有数字签名。还必须再花一些工夫,让Java虚拟机信任的一个证书发行者信任我,为我提供一个证书,我再用这个证书为JAR文件签名。浏览器插件不再运行不信任的applet。与过去相比,这是一个很大的变化,原先在屏幕上绘制像素的简单applet会限制在“沙箱”中,即使没有签名也可以工作。可惜,即使是Oracle也不再相信沙箱的安全性了。
为了解决这个问题,可以临时将Java配置为信任本地文件系统的applet。首先,打开Java控制面板。
在Windows中,查看控制面板中的Programs(程序)部分。
在Mac上,打开System Preferences(系统首选项)。
在Linux上,运行jcontrol。
然后点击Security(安全)标签页和Edit Site List(编辑网站列表)按钮。再点击Add(增加),并键入f?ile:///。点击OK,接受下一个安全提示,然后再次点击OK(见图2-10)。
现在应该可以在浏览器中加载文件corejava/v1ch02/RoadApplet/RoadApplet.html,applet将随周围的文本一同显示。结果如图2-11所示。
最后,在程序清单2-4中给出了这个applet类的代码。现在,只需要简单看一下。在第13章中,还会再来介绍applet的编写。
图2-10 配置Java信任本地applet
图2-11 在浏览器中运行RoadApplet
程序清单2-4 RoadApplet/RoadApplet.java
在本章中,我们学习了有关编译和运行Java程序的机制。现在可以转到第3章开始学习Java语言了。
第3章 Java的基本程序设计结构
一个简单的Java应用程序 ▲
现在,假定已经成功地安装了JDK,并且能够运行第2章中给出的示例程序。我们从现在开始将介绍Java应用程序设计。本章主要介绍程序设计的基本概念(如数据类型、分支以及循环)在Java中的实现方式。
非常遗憾,需要告诫大家,使用Java编写GUI应用程序并不是一件很容易的事情,编程者需要掌握很多相关的知识才能够创建窗口、添加文本框以及能响应的按钮等。介绍基于GUI的Java应用程序设计技术与本章将要介绍的程序设计基本概念相差甚远,因此本章给出的所有示例都是为了说明一些相关概念而设计的“玩具式”程序,它们仅仅使用终端窗口提供输入输出。
最后需要说明,对于一个有C++编程经验的程序员来说,本章的内容只需要浏览一下,应该重点阅读散布在正文中的C/C++注释。对于具有使用Visual Basic等其他编程背景的程序员来说,可能会发现其中的绝大多数概念都很熟悉,但是在语法上有比较大的差异,因此,需要非常仔细地阅读本章的内容。
3.1 一个简单的Java应用程序
下面看一个最简单的Java应用程序,它只发送一条消息到控制台窗口中:
这个程序虽然很简单,但所有的Java应用程序都具有这种结构,还是值得花一些时间来研究。首先,Java区分大小写。如果出现了大小写拼写错误(例如,将main拼写成Main),程序将无法运行。
下面逐行地查看一下这段源代码。关键字public称为访问修饰符(access modif?ier),这些修饰符用于控制程序的其他部分对这段代码的访问级别。在第5章中将会更加详细地介绍访问修饰符的具体内容。关键字class表明Java程序中的全部内容都包含在类中。这里,只需要将类作为一个加载程序逻辑的容器,程序逻辑定义了应用程序的行为。在第4章中将会用大量的篇幅介绍Java类。正如第1章所述,类是构建所有Java应用程序和applet的构建块。Java应用程序中的全部内容都必须放置在类中。
关键字class后面紧跟类名。Java中定义类名的规则很宽松。名字必须以字母开头,后面可以跟字母和数字的任意组合。长度基本上没有限制。但是不能使用Java保留字(例如,public或class)作为类名(保留字列表请参看附录A)。
标准的命名规范为(类名FirstSample就遵循了这个规范):类名是以大写字母开头的名词。如果名字由多个单词组成,每个单词的第一个字母都应该大写(这种在一个单词中间使用大写字母的方式称为骆驼命名法。以其自身为例,应该写成CamelCase)。
源代码的文件名必须与公共类的名字相同,并用.java作为扩展名。因此,存储这段源代码的文件名必须为FirstSample.java(再次提醒大家注意,大小写是非常重要的,千万不能写成f?irstsample.java)。
如果已经正确地命名了这个文件,并且源代码中没有任何录入错误,在编译这段源代码之后就会得到一个包含这个类字节码的文件。Java编译器将字节码文件自动地命名为FirstSample. class,并与源文件存储在同一个目录下。最后,使用下面这行命令运行这个程序:
(请记住,不要添加.class扩展名。)程序执行之后,控制台上将会显示“We will not use ‘Hello,World’!”。
运行已编译的程序时,Java虚拟机将从指定类中的main方法开始执行(这里的“方法”就是Java中所说的“函数”),因此为了代码能够执行,在类的源文件中必须包含一个main方法。当然,也可以将用户自定义的方法添加到类中,并且在main方法中调用它们(第4章将讲述如何自定义方法)。
注释:根据Java语言规范,main方法必须声明为public(Java语言规范是描述Java语言的官方文档。可以从网站http://docs.oracle.com/javase/specs上阅读或下载)。
不过,当main方法不是public时,有些版本的Java解释器也可以执行Java应用程序。有个程序员报告了这个bug。如果感兴趣的话,可以在网站http://bugs.java.com/ bugdatabase/ index.jsp上输入bug号码4252539查看。这个bug被标明“关闭,不予修复。”Sun公司的工程师解释说:Java虚拟机规范(在http://docs.oracle.com/javase/specs/jvms/se8/html)并没有要求main方法一定是public,并且“修复这个bug有可能带来其他的隐患”。好在,这个问题最终得到了解决。在Java SE 1.4及以后的版本中强制main方法是public的。
从上面这段话可以发现一个问题的两个方面。一方面让质量保证工程师判断在bug报告中是否存在问题是一件很头痛的事情,这是因为其工作量很大,并且工程师对Java的所有细节也未必了解得很清楚。另一方面,Sun公司在Java开源很久以前就把bug报告及其解决方案放到网站上让所有人监督检查,这是一种非常了不起的举动。某些情况下,Sun甚至允许程序员为他们最厌恶的bug投票,并用投票结果来决定发布的下一个JDK版本将修复哪些bug。
需要注意源代码中的括号{ }。在Java中,像在C/C++中一样,用大括号划分程序的各个部分(通常称为块)。Java中任何方法的代码都用“{”开始,用“}”结束。
大括号的使用风格曾经引发过许多无意义的争论。我们的习惯是把匹配的大括号上下对齐。不过,由于空白符会被Java编译器忽略,所以可以选用自己喜欢的大括号风格。在下面讲述各种循环语句时,我们还会详细地介绍大括号的使用。
我们暂且不去理睬关键字static void,而仅把它们当作编译Java应用程序必要的部分就行了。在学习完第4章后,这些内容的作用就会揭晓。现在需要记住:每个Java应用程序都必须有一个main方法,其声明格式如下所示:
C++注释:作为一名C++程序员,一定知道类的概念。Java的类与C++的类很相似,但还是有些差异会使人感到困惑。例如,Java中的所有函数都属于某个类的方法(标准术语将其称为方法,而不是成员函数)。因此,Java中的main方法必须有一个外壳类。读者有可能对C++中的静态成员函数(static member functions)十分熟悉。这些成员函数定义在类的内部,并且不对对象进行操作。Java中的main方法必须是静态的。最后,与C/C++一样,关键字void表示这个方法没有返回值,所不同的是main方法没有为操作系统返回“退出代码”。如果main方法正常退出,那么Java应用程序的退出代码为0,表示成功地运行了程序。如果希望在终止程序时返回其他的代码,那就需要调用System.exit方法。
接下来,研究一下这段代码:
一对大括号表示方法体的开始与结束,在这个方法中只包含一条语句。与大多数程序设计语言一样,可以将Java语句看成是这种语言的句子。在Java中,每个句子必须用分号结束。特别需要说明,回车不是语句的结束标志,因此,如果需要可以将一条语句写在多行上。
在上面这个main方法体中只包含了一条语句,其功能是:将一个文本行输出到控制台上。
在这里,使用了System.out对象并调用了它的println方法。注意,点号(·)用于调用方法。Java使用的通用语法是
这等价于函数调用。
在这个示例中,调用了println方法并传递给它一个字符串参数。这个方法将传递给它的字符串参数显示在控制台上。然后,终止这个输出行,使得每次调用println都会在新的一行上显示输出。需要注意一点,Java与C/C++一样,都采用双引号分隔字符串。(本章稍后将会详细地讲解有关字符串的知识)。
与其他程序设计语言中的函数一样,在Java的方法中,可以没有参数,也可以有一个或多个参数(有的程序员把参数叫做实参)。对于一个方法,即使没有参数也需要使用空括号。例如,不带参数的println方法只打印一个空行。使用下面的语句来调用:
注释:System.out还有一个print方法,它在输出之后不换行。例如,System.out.print(“Hello”)打印“Hello”之后不换行,后面的输出紧跟在字母“o”之后。
与大多数程序设计语言一样,Java中的注释也不会出现在可执行程序中。因此,可以在源程序中根据需要添加任意多的注释,而不必担心可执行代码会膨胀。在Java中,有3种标记注释的方式。最常用的方式是使用//,其注释内容从//开始到本行结尾。
当需要长篇的注释时,既可以在每行的注释前面标记//,也可以使用/*和*/将一段比较长的注释括起来。
最后,第3种注释可以用来自动地生成文档。这种注释以/**开始,以*/结束。请参见程序清单3-1。有关这种注释的详细内容和自动生成文档的具体方法请参见第4章。
程序清单3-1 FirstSample/FirstSample.java
警告:在Java中,/* */注释不能嵌套。也就是说,不能简单地把代码用/*和*/括起来作为注释,因为这段代码本身可能也包含一个*/。
3.3 数据类型
Java是一种强类型语言。这就意味着必须为每一个变量声明一种类型。在Java中,一共有8种基本类型(primitive type),其中有4种整型、2种浮点类型、1种用于表示Unicode编码的字符单元的字符类型char(请参见论述char类型的章节)和1种用于表示真值的boolean类型。
注释:Java有一个能够表示任意精度的算术包,通常称为“大数值”(big number)。虽然被称为大数值,但它并不是一种新的Java类型,而是一个Java对象。本章稍后将会详细地介绍它的用法。
3.3.1 整型
整型用于表示没有小数部分的数值,它允许是负数。Java提供了4种整型,具体内容如表3-1所示。
表3-1 Java整型
类型 存储需求 取值范围
int 4字节 -2 147 483 648~2 147 483 647(正好超过20亿)
short 2字节 -32 768~32 767
long 8字节}

我要回帖

更多关于 java lang null 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信