目录
第1章 成为程序员 1.1 选择编程语言 1.2 告诉计算机做什么 1.3 程序的工作原理 1.4 为什么程序不能正常工作 1.5 选择 Java编程工具 1.6 安装 Java开发工具 1.7 总结 1.8 问与答 1.9 测验 1.9.1 问题 1.9.2 答案 1.10 练习 第2章 编写第一个程序 2.1 编写程序所需的工具 2.2 创建 Saluton 程序 2.3 开始输入程序 2.3.1 class语句 2.3.2 main语句的作用 2.3.3 大括号 2.4 在变量中存储信息 2.5 保存编写好的程序 2.6 将程序编译为 class文件 2.7 修复错误 2.8 运行 Java程序 2.9 总结 2.10 问与答 2.11 测验 2.11.1 问题 2.11.2 答案 2.12 练习 第3章 Java之旅 3.1 第一站:Oracle 3.2 去 Java学校 3.3 在 JavaWorld 用午餐 3.4 在 NASA仰望天穹 3.5 回归正题 3.6 到 Java Boutique 去问路 3.7 在手机上运行 Java 3.8 总结 3.9 问与答 3.10 测验 3.10.1 问题 3.10.2 答案 3.11 练习 第4章 理解Java程序的工作原理 4.1 创建应用程序 4.2 向应用程序传递参数 4.3 创建 applet 4.4 总结 4.5 问与答 4.6 测验 4.6.1 问题 4.6.2 答案 4.7 练习 第5章 在程序中存储和修改信息 5.1 语句和表达式 5.2 指定变量类型 5.2.1 整数和浮点数 5.2.2 字符和字符串 5.2.3 其他数值类型的变量 5.2.4 布尔型变量 5.3 给变量命名 5.4 在变量中存储信息 5.5 运算符 5.5.1 变量的递增与递减 5.5.2 运算符优先级 5.6 使用表达式 5.7 总结 5.8 问与答 5.9 测验 5.9.1 问题 5.9.2 答案 5.10 练习 第6章 使用字符串来交流 6.1 在字符串中存储文本 6.2 在程序中显示字符串 6.3 在字符串中使用特殊字符 6.4 拼接字符串 6.5 将其他变量用于字符串中 6.6 字符串的高级处理 6.6.1 比较两个字符串 6.6.2 确定字符串的长度 6.6.3 改变字符串的大小写 6.6.4 查找字符串 6.7 导演及演员名单 6.8 总结 6.9 问与答 6.10 测验 6.10.1 问题 6.10.2 答案 6.11 练习 第7章 使用条件测试进行判断 7.1 if语句 7.1.1 小于和大于的比较 7.1.2 相等和不等 7.1.3 使用块语句组织程序 7.2 if-else 语句 7.3 switch语句 7.4 条件运算符 7.5 观察时钟 7.6 总结 7.7 问与答 7.8 测验 7.8.1 问题 7.8.2 答案 7.9 练习 第8章 使用循环重复执行操作 8.1 for循环 8.2 while 循环 8.3 do-while 循环 8.4 退出循环 8.5 给循环命名 8.6 测试计算机的运行速度 8.7 总结 8.8 问与答 8.9 测验 8.9.1 问题 8.9.2 答案 8.10 练习 第9章 使用数组存储信息 9.1 创建数组 9.2 使用数组 9.3 多维数组 9.4 对数组进行排序 9.5 对字符串中的字符计数 9.6 总结 9.7 问与答 9.8 测验 9.8.1 问题 9.8.2 答案 9.9 练习 第10章 创建第一个对象 10.1 面向对象编程的工作原理 10.2 对象示例 10.3 什么是对象 10.4 理解继承 10.5 建立继承层次 10.6 转换对象和简单变量 10.6.1 简单变量的类型转换 10.6.2 对象类型转换 10.6.3 在简单变量和对象之间进行转换 10.6.4 自动封装和拆封 10.7 创建对象 10.8 总结 10.9 问与答 10.10 测验 10.10.1 问题 10.10.2 答案 10.11 练习 第11章 描述对象 11.1 创建变量 11.2 创建类变量 11.3 用方法来创建行为 11.3.1 声明方法 11.3.2 参数不同的类似方法 11.3.3 构造函数 11.3.4 类方法 11.3.5 方法中变量的作用域 11.4 将一个类放在另一个类中 11.5 使用关键字this 11.6 使用类方法和类变量 11.7 总结 11.8 问与答 11.9 测验 11.9.1 问题 11.9.2 答案 11.10 练习 第12章 充分利用现有对象 12.1 继承的威力 12.1.1 继承行为和属性 12.1.2 覆盖方法 12.2 建立继承 12.3 使用现有的对象 12.4 将相同类型的对象存储到 Vector 中 12.5 创建子类 12.6 总结 12.7 问与答 12.8 测验 12.8.1 问题 12.8.2 答案 12.9 练习 第13章 创建简单的用户界面 13.1 Swing 和抽象窗口工具包 13.2 使用组件 13.2.1 窗口和框架 13.2.2 按钮 13.2.3 标签和文本框 13.2.4 复选框 13.2.5 组合框 13.2.6 文本区域 13.2.7 面板 13.3 创建自己的组件 13.4 总结 13.5 问与答 13.6 测验 13.6.1 问题 13.6.2 答案 13.7 练习 第14章 用户界面的布局 14.1 使用布局管理器 14.1.1 GridLayout管理器 14.1.2 BorderLayout管理器 14.1.3 BoxLayout管理器 14.1.4 使用Insets将组件隔开 14.2 应用程序的界面布局 14.3 总结 14.4 问与答 14.5 测验 14.5.1 问题 14.5.2 答案 14.6 练习 第15章 响应用户输入 15.1 让程序监听 15.2 设置要监听的组件 15.3 处理用户事件 15.3.1 复选框和组合框事件 15.3.2 键盘事件 15.3.3 启用和禁用组件 15.4 完善图形应用程序 15.5 总结 15.6 问与答 15.7 测验 15.7.1 问题 15.7.2 答案 15.8 练习 第16章 创建复杂的用户界面 16.1 滚动窗格 16.2 滑块 16.3 变更监听器 16.4 使用图像图标和工具栏 16.5 总结 16.6 问与答 16.7 测验 16.7.1 问题 16.7.2 答案 16.8 练习 第17章 创建交互式Web程序 17.1 标准applet方法 17.1.1 在applet窗口中绘画 17.1.2 初始化applet 17.1.3 启动和停止applet 17.1.4 销毁applet 17.2 将applet放到Web页面中 17.3 创建applet 17.3.1 在applet窗口中绘画 17.3.2 测试SalutonApplet程序 17.4 从Web页面传递参数 17.5 在applet中接收参数 17.6 在applet中处理参数 17.7 使用object标记 17.8 总结 17.9 问与答 17.10 测验 17.10.1 问题 17.10.2 答案 17.11 练习 第18章 处理程序中的错误 18.1 异常 18.1.1 在try-catch块中捕获异常 18.1.2 捕获多种不同的异常 18.1.3 出现异常后进行处理 18.1.4 抛出异常 18.1.5 忽略异常 18.2 抛出和捕获异常 18.3 总结 18.4 问与答 18.5 测验 18.5.1 问题 18.5.2 答案 18.6 练习 第19章 创建线程程序 19.1 线程 19.1.1 降低程序的速度 19.1.2 创建线程 19.2 使用线程 19.2.1 声明类 19.2.2 创建变量 19.3 从init( )开始 19.4 在创建URL时捕获错误 19.5 在paint( )方法中处理屏幕更新 19.6 启动线程 19.6.1 运行线程 19.6.2 停止线程 19.7 处理鼠标单击 19.8 循环显示链接 19.9 总结 19.10 问与答 19.11 测验 19.11.1 问题 19.11.2 答案 19.12 练习 第20章 读写文件 20.1 流 20.1.1 文件 20.1.2 从流中读取数据 20.1.3 缓冲输入流 20.2 将数据写入流中 20.3 读写配置属性 20.4 总结 20.5 问与答 20.6 测验 20.6.1 问题 20.6.2 答案 20.7 练习 第21章 读写XML数据 21.1 创建XML文件 21.2 读取XML文件 21.3 读取 RSS 聚合内容(Syndication Feeds) 21.4 总结 21.5 问与答 21.6 测验 21.6.1 问题 21.6.2 答案 21.7 练习 第22章 利用JAX-WS开发Web服务 22.1 定义服务端点接口 使用注解来简化Java代码 22.2 创建服务实现Bean 22.3 发布Web服务 22.4 使用Web服务描述语言文件 22.5 创建Web服务客户端 22.6 总结 22.7 问与答 22.8 测验 22.8.1 问题 22.8.2 答案 22.9 练习 第23章 创建Java2D图形 23.1 使用Font类 23.2 使用Color类 23.3 创建自定义颜色 23.4 绘制直线和形状 23.4.1 绘制直线 23.4.2 绘制矩形 23.4.3 绘制椭圆和圆 23.4.4 绘制弧线 23.5 绘制饼图 23.6 总结 23.7 问与答 23.8 测验 23.8.1 问题 23.8.2 答案 23.9 练习 第24章 编写Android app 24.1 Android简介 24.2 创建 Android app 24.2.1 剖析一个Android新项目 24.2.2 创建app 24.2.3 安装Android模拟器 24.2.4 创建调试配置 24.3 运行app 24.4 设计真实的app 24.4.1 组织资源 24.4.2 配置app的Manifest文件 24.4.3 设计用户界面 24.4.4 编写Java代码 24.5 总结 24.6 问与答 24.7 测验 24.7.1 问题 24.7.2 答案 24.8 练习 附录A 使用NetBeans IDE A.1 安装NetBeans A.2 创建新项目 A.3 创建新的Java类 A.4 运行应用程序 A.5 修复错误 附录B Java资源 B.1 可以考虑的其他书 B.2 Oracle公司的 Java官方站点 B.3 其他Java站点 B.3.1 本书英文版的配套网站 B.3.2 Café au Lait B.3.3 Workbench B.3.4 Java 7 Developer Blog B.3.5 其他Java博客 B.3.6 InformIT B.3.7 Stack Overflow B.3.8 Java Review Service B.3.9 JavaWorld杂志 B.3.10 Developer.com’s Java Directory 附录C 本书站点 附录D 设置Android开发环境 D.1 起步 D.2 安装Eclipse D.3 安装 Android SDK D.4 安装在Eclipse中使用的Android插件 D.5 设置你的手机 其他 版权

Java初级教程

Java入门经典
第10章 创建第一个对象

本章介绍如下内容:

创建对象;

使用属性描述对象;

确定对象的行为;

合并对象;

从其他对象继承;

转换对象和其他类型的信息。

在本书中,面向对象编程(OOP)是比较难理解的专业术语之一。这个复杂的术语以优雅的方式描述了计算机程序是什么以及他是如何工作的。

在面向对象编程之前,计算机程序是使用本书前面介绍过的最简单的定义来描述的:它是文件中的一组指令,这些指令按某种可靠的顺序执行。

如果将程序视为对象的集合,便可以确定程序要完成的任务,然后将这些任务指派给最适合完成它们的对象。

10.1 面向对象编程的工作原理

用Java创建的程序可被视为一个对象,就像真实世界中存在的物体一样。对象独立于其他对象而存在,以特定方式同其他对象交互,可以与其他对象合并成更大的事务。如果将计算机程序视为一组彼此交互的对象,设计出的程序将更可靠,更容易理解,更容易在其他项目中重用。

在第23章,读者将创建一个显示饼图的Java程序,饼图是一个圆,使用不同颜色的扇形区表示数据(见图10.1)。饼图是一个由更小的对象(具有不同颜色的扇形区域、指出每个扇形区代表什么的图例以及标题)组成的对象。

图10.1 显示饼图的 Java程序

每个对象都有区别于其他对象的特征。饼图是圆的,而柱状图则使用一系列矩形来表示数据。如果你用划分饼图的方式划分计算机程序,也就是在进行面向对象编程(OOP)。在面向对象编程中,对象包含两项内容:属性和行为。属性描述对象并使其不同于其他对象,而行为指的是对象能做什么。

在 Java 中,创建对象时使用类作为模板,“类”是对象的母版,它可以决定对象应有哪些属性和行为。读者对术语“类”应该不陌生,因为每个 Java 程序都被称为类。使用 Java创建的每个程序都是类,你可以可它用作创建新对象的模板。例如,任何使用字符串的Java程序都使用了根据String 类创建的对象。String类包含属性和行为,前者决定了String 对象是什么样的,而后者控制String对象能做什么。

在面向对象编程中,计算机程序是一组对象,这些对象协同工作以完成某项任务。有些简单的程序看似由一个对象(类文件)组成,但即使是这样的程序也使用了其他对象来完成其工作。

10.2 对象示例

在显示饼图的程序中,PieChart对象可能包含以下内容:

计算饼图中每个扇形区应多大的行为;

绘制饼图的行为;

存储饼图标题的属性。

对读者来说,让PieChart来绘制它自己可能会有点奇怪,因为现实世界中图形无法绘制自身。但在面向对象编程中,对象尽可能独立地完成工作。这种特征使对象更有用,因为可以将其用于其他程序,而不用教它如何做。如果PieChart对象不知道如何绘制自己,则每当在其他程序中使用PieChart对象时,你都必须创建绘制它的行为。

面向对象编程的另一个例子是自动拨号器。在电影《War Games》中,Matthew Broderick扮演的角色使用它寻找可入侵的计算机。

注意:

自动拨号器是一个软件,它使用调制解调器依次拨打一系列电话号码。这种程序旨在找到做出应答的计算机,以便以后拨打这些电话号码,看看是哪里的电话。

当前,使用自动拨号器肯定会引起本地电话公司的关注,甚至带来法律纠纷。但在1980年代,几乎不用出门就能做到。David Lightman(Broderick 扮演的角色)使用自动拨号器搜索一家视频游戏公司的私有计算机系统,以便在该公司发布前就能玩其新游戏。结果Lightman 找到了一台秘密的政府计算机,在该计算机上能够玩从国际象棋到《Global Therm- onuclear War》在内的所有游戏。

和其他任何计算机程序一样,自动拨号器可以视为一组协同工作的对象。它可能有以下几部分组成。

Modem对象:它具有自己的属性(比如速度)以及行为。比如,该对象能够让调制解调器拨出一个号码,并检测到另外一个计算机系统响应了该呼叫。

Monitor对象:对所呼叫的号码和成功的呼叫进行记录。

每个对象都独立于其他对象存在。

设计完全独立的 Modem 对象的一个优点是,可以将其用在需要调制解调器功能的其他程序中。

使用自包含对象的另一个原因是更容易调试。计算机程序的规模越来越大,如果你在调试Modem等对象时,你知道它不依赖于其他任何东西,则只需将精力放在确保Modem对象完成其预期工作,并存储完成其工作所需的信息即可。

将Java等面向对象编程语言作为学习的第一种编程语言是有好处的,因为这样不必改正原有的编程习惯。

10.3 什么是对象

对象是通过将对象类作为模板来创建的。下面的语句将创建一个类。

根据这个类创建的对象毫无用处,因为它没有任何属性和行为。只有为其添加了属性和行为后,这个类才具有可用性。可以像下面这样为这个类添加属性和行为。

这个Modem类看起来应该很像本书前面编写的程序。Modem类以class语句打头,只是class左边还有关键字public。关键字public表示这个类是公有的,换句话说,任何程序都可以使用Modem对象。

Modem类的第一部分创建一个整型变量speed,该变量是对象的一个属性。

Modem类的第二部分是一个名为displaySpeed( )的方法。该方法是对象的行为的一部分,它包含一条语句:System.out.println( ),用于显示调制解调器的速度值。

对象的变量通常称为实例变量或成员变量。

如果要在程序中使用Modem对象,可以使用如下语句来创建它。

这条语句创建一个名为device的Modem对象。在创建了对象之后,可以设置其变量并调用其方法。要设置device对象的speed变量的值,可使用下面的语句:

通过调用 displaySpeed( )方法可以让这个调制解调器显示其速度,如下面的代码所示:

名为 device的 Modem对象将通过显示文本“Speed: 28800”来响应这条语句。

10.4 理解继承

OOP的一个最大优点是继承,它允许一个对象继承另外一个对象的行为和属性。

当你开始创建对象时,有时会发现将要创建的新对象和你以往开发出的对象有很多相似之处。

当《War Games》在 1983 年上映之时,如果 David Lightman 想要一个能够处理纠错且具有其他高级调制解调器特性的对象,而这些特性在当时还没有,那么他应该怎么办呢?Lightman 可以通过复制 Modem 对象的语句然后对其修改的方式,来创建一个新的 Error CorrectionModem 对象。然而,如果 ErrorCorrectionModem 对象的大部分属性和行为与Modem对象相同,则上述工作完全没有必要。这也意味着如果日后要进行修改,Lightman需要升级两个独立的程序。

通过继承,程序员只需定义新类与现有类的不同之处,就能够创建一个新类。Lightman可以让 ErrorCorrectionModem类继承 Modem类,这样只需编写纠错调制解调器不同于以前调制解调器的部分。

要继承其他类,可使用extend语句,下面是从Modem类继承的ErrorCorrectionModem类的框架:

10.5 建立继承层次

通过继承,无须做大量重复的工作就可以开发大量相关的类,它使得代码可以从一个类传递给另一个类,再传递给其他类。类这种组织结构称为类层次,在Java程序中使用的标准类都属于同一个类层次。

如果知道子类和超类是什么,将更容易理解类层次。从其他类继承而来的类称为子类,被继承的类称为超类。

在前面的《War Games》示例中,Modem类是 ErrorCorrectionModem类的超类;而 Error CorrectionModem是Modem的子类。

在层次结构中,可以从一个类派生出多个类:ISDNModem可能是Modem的另外一个子类,因为 ISDN Modem包含使其不同于纠错调制解调器的属性和行为。如果 ErrorCorrection Modem有子类IntenalErrorCorrectionModem,后者将继承类层次结构中位于它上面的所有类,包括ErrorCorrectionModem和Modem。这些继承关系如图10.2所示。

图10.2 类层次示例

组成标准Java语言的类充分利用了继承,了解这一点很有必要。第12章将详细地介绍继承。

10.6 转换对象和简单变量

在Java中需要完成的一种最常见的任务是,将信息从一种格式转换为另一种格式。可以执行多种转换,如下所示:

将一个对象转换为另一个对象;

将简单变量转换为另一种类型的变量;

使用对象创建简单变量;

使用简单变量创建对象。

简单变量的类型为第5章介绍的基本数据类型,包括int、float、char、long和double。

在程序中使用方法或表达式时,必须使用方法或表达式所要求的信息类型。例如,如果需要Calendar对象的方法必须接收Calendar对象。如果使用的方法接受单个整型参数,但传递的却是浮点数,在编译程序时将报错。

注意:

诸如System.out.println()这样的方法需要字符串参数时,你可以使用+运算符将参数中不同类型的信息合并起来。只要待合并中的信息有一个是字符串,则合并后的参数将被转换为字符串。

在程序中将信息转换为另一种类型称为类型转换。类型转换得到的信息的类型与原来的变量或对象不同。进行类型转换时,并不会修改原来的变量或对象的值,而是创建一个所需类型的新变量或对象。

讨论类型转换时,术语“源”和“目标”很有帮助。“源”指的是原始格式的信息(无论是变量还是对象),而“目标”是转换后得到的新版本。

10.6.1 简单变量的类型转换

对于简单变量,最常见的是在数值类型之间进行类型转换,如整数和浮点数之间。有一种类型的变量不能进行类型转换,这就是布尔值。

要将信息转换为其他类型,可以在变量前指定新类型,并将其用括号括起。例如,要将变量转换为long变量,可在前面加上(long)。下面的语句将下面的语句将float值转换为int值:

在类型转换中,如果目标类型的取值范围比源类型大,转换将很容易,如将byte值转换为int值。byte的取值范围为−128~127,而int的取值范围为−2.1×109~2.1×109。无论byte变量存储的什么值,新的int变量都有足够的空间存储它。

有时不用进行类型转换就可使用类型不同的变量,例如,char变量可直接用作int变量, int变量可直接用作long变量,而任何数值变量都可直接用作double变量。

在大多数情况下,由于目标类型的取值范围大于源类型,转换时不会修改信息。特例是将int或long变量转换为float变量,以及将long变量转换为double变量。

要从取值范围大的类型转换为取值范围小的类型,必须显式地进行转换,如下面的语句所示:

这里将一个名为xNum的int变量转换为一个名为val的byte变量。在这里,目标变量的取值范围比源类型小,byte变量能够存储−128~127的整数,而int变量的取值范围大得多。

如果在转换操作中,源变量的值在目标变量中放不下,Java将修改源值,以便能够存储。如果不想改变值,这将导致意想不到的结果。

10.6.2 对象类型转换

只要源对象和目标对象存在继承关系,就可以在它们之间进行类型转换,其中一个类必须是另一个类的子类。

有些对象根本不需要转换,可在任何需要超类的地方使用子类对象。Java中的所有对象都是Object类的子类,因此可在任何需要Object的地方使用任何对象。

也可以将对象用于需要其子类的地方,然而,由于子类通常比其超类包含更多的信息,因此可能缺少某些信息。如果对象没有其子类的方法,而程序使用了该方法,这将导致错误。

要将对象用于需要其子类的地方,必须使用类似于下面的语句对其进行显式的类型转换:

这将Graphics对象comp转换为一个Graphics2D对象。转换过程中不会丢失任何信息,但将得到子类定义的所有方法和变量。

10.6.3 在简单变量和对象之间进行转换

不能在对象和简单变量之间进行类型转换。在Java中,每一个简单的变量类型都有很多类,比如Boolean、Byte、Character、Double、Float、Integer、Long和Short等。这些类名的首字母都是大写的,而不是简单变量类型。

使用这些类中定义的类方法,可以将变量的值作为参数来创建一个对象。下面的语句使用5309创建一个Integer对象:

用这种方式创建对象后,可以像使用其他对象那样使用该对象。需要将该值作为简单变量使用时,也可以使用相应的类方法。例如,要通过前面的suffix对象得到一个int值,可使用下面的语句:

这条语句将变量newSuff的值设置为5309,该变量的类型为int。最常见的在对象和变量之间进行的转换是将字符串作为数值使用。为此,可以使用 Integer 类的 parseInt( )方法,如下例所示:

该语句将包含文本25的字符串转换为整型值25。如果字符串的值不是有效的证书,则不进行转换。

接下来将创建一个应用程序,它将命令行参数中的字符串值转换为数值,这是通过命令行从用户那里获得输入时常用的一种技巧。

在 NetBeans中打开 Java24 项目,选择 File->New File,创建一个新的 Java 空文件,并命名为NewRoot。在源代码编辑器中输入程序清单10.1中的内容,然后保存。

程序清单10.1 NewRoot.java的全部代码

在运行该程序之前,必须对NetBean进行配置,使其能够运行命令行参数。选择菜单命令 Run->Set Project Configuration->Customize,打开 Project Properties对话框。将主类命名为NewRoot,并在参数字段中输入169。单击OK按钮关闭对话框。

选择 Run->Run Main Project(而不是Run File)来运行该程序。该程序将显示数值 169以及该数值的平方根,如图10.3所示。

应用程序NewRoot是第4章示例程序的扩展,后者显示整数225的平方根。

图10.3 NewRoot 程序的输出

如果该程序能够接受用户提交的整数并显示其平方根,将更有用。这就需要将字符串转换为整数。每个命令行参数都被存储在String数组的元素中,因此在数学表达式中使用它们之前,必须将其转换为数字。

为了根据字符串的内容创建一个整数值,可调用 Interger.parseInt( )方法,并将字符串作为唯一的参数,就像第5行那样:

由于 args[0]存储的是程序运行时用户提供的第一个参数,因此当以“169”作为参数来运行该程序时,字符串“169”被转换为整数169。

10.6.4 自动封装和拆封

在Java中,每一种基本的数据类型都有对应的类:boolean对应Boolean类,byte对应Byte类,char对应Character类,double对应Double类,float对应Float类,int对应Integer类,long对应Long类,short对应Short类。

在每种基本类型及其对应的类中,可存储的值是相同的,唯一的差别是信息的格式。例如,整数值413可以用int变量表示,也可以用Integer对象表示。

Java的自动封装和拆封功能使得可以互换地使用基本数据类型及其对应的对象格式。

自动封装功能将简单变量值转换为相对应的类。

拆封功能将对象转换为相对应的简单变量值。

这些功能在幕后工作,确保在需要基本数据类型(比如float)时,将对象转换为该类型且值保持不变。反之亦然,即必要时自动将基本数据类型转换为相应的对象。

下面的语句显示的是自动封装和拆封是如何使用的。

在 Java 的早期版本中(Java 1.5 之前),这将会报错,原因是不能在第二条语句中使用Float对象。Java现在可以拆封total对象以让该语句运行,从而sum的最终结果是0.26。

10.7 创建对象

下面来看一个关于类和继承的例子,为此需要创建代表两种对象类型的类:一种是电缆调制解调器,对应的类为CableModem;另一种是DSL调制解调器,对应的类为DslModem这里将重点放在这些对象的简单属性和行为上:

每个对象都有速度(speed),并可以显示出来;

每个对象都应能够连接到Internet。

电缆调制解调器和 DSL 调制解调器的一个共同点是,它们都有速度。因为这是它们共有的,可将其放在CableModem和DslModem的超类Modem中。在NetBeans中创建一个新的Java空类,将其命名为Modem,然后在源代码编辑器中输入程序清单10.2中的文本,并保存。

程序清单10.2 Modem.java的完整源代码

该文件将被自动编译为 Modem.class。该程序不能直接运行,但是可以在其他类中使用它。这个Modem类可以处理CableModem和DslModem类共有的行为。创建类CableModem和DslModem时,通过使用extends语句可以使其都成为Modem的子类。

在NetBeans中创建一个新的Java空文件,将其命名为CableModem。输入程序清单10.3中的文本,然后进行保存。

程序清单10.3 CableModem.java的完整源代码

在NetBeans中创建第3个文件,将其命名为DslModem。输入程序清单10.4中的文本,然后保存。

程序清单10.4 DslModem.java的完整源代码

如果此时没有错误,将会得到3个类文件:Modem.class、CableModem.class和DslModem. class。然而,此时不能运行这 3 个类文件的任何一个,因为它们都没有 main( )块。需要创建一个小程序来测试刚才建立的类层次。

返回NetBeans,然后创建一个新的Java空文件,将其命名为ModemTester。在源代码编辑器中输入程序清单10.5中的文本,然后保存。

程序清单10.5 ModemTester.java的完整源代码

当运行该程序时,就会看到图10.4所示的输出。

图10.4 ModemTester程序的输出

下面是对该程序的详细解释。

第3~4行:创建两个新对象,一个是名为surfBoard的CableModem对象,另一个是名为gateway的DslModem对象。

第5行:将CableModem对象surfBoard的speed变量设置为500000。

第6行:将DslModem对象gateway的speed变量设置为400000。

第 8 行:调用 surfBoard 对象的 displaySpeed( )方法,该方法是从 Modem类继承的,虽然CableModem类中没有这个方法,但也可以调用它。

第 9 行:调用 surfBoard 对象的 connect( )方法。

第 11 行:调用 gateway 对象的 displaySpeed( )方法。

第 12 行:调用 gateway 对象的 connect( )方法。

10.8 总结

创建第一个对象类并建立包含几个类的层次结构后,读者应该对术语“面向对象编程”有更深的理解。在接下来的两章中,读者将开始创建更复杂的对象,学到更多有关对象行为和属性的知识。

有了更多面向对象编程的经验后,读者将更深入地理解术语“程序”、“类”和“对象”的含义。面向对象编程需要花段时间才能习惯,但一旦掌握它,将发现它是一种设计、开发和调试计算机程序的高效方式。

10.9 问与答

问:一个类可以继承多个类吗?

答:这在有些编程语言中(比如C++)是可以的,但在Java中不行。多继承是一项功能强大的特性,但也使得面向对象编程更难于学习和使用。Java的开发者决定对继承进行限制,即任何类只能有一个超类,虽然同一个类可以有多个子类。一种补偿这种限制的方式是,可以从接口这种特殊类继承方法。第19章将更详细地介绍接口。

问:什么时候应创建非public的方法?

答:当你不想让方法被其他程序使用时,就需要对该方法进行限制,使其仅用于你编写的程序。如果创建了一款游戏程序,而且你编写的 shootRayGun( )方法仅适合用于该游戏,可将其声明为private的。要将方法声明为private的,可省略方法名前面的public。

问:为什么可将char值当做int值来使用?

答:由于每一个字符在字符集中都有一个可以表示其位置的数值代码,因此可将字符值当做int值来使用。如果有一个变量k,其值为67,则对(char)k进行转换时,则会生成字符值'C',原因是在ASCII字符集中,与大写字母C 对应的数值代码是67。ASCII字符集是Unicode字符标准的一个子集,其中后者由Java语言采用。

10.10 测验

回答下面的问题,以测试读者对有关对象及使用对象的程序的理解程度。

10.10.1 问题

1.什么语句让一个类能够继承另一个类?

a.inherits。

b.extends。

c.handitOverAndNobodyGetsHurt。

2.为什么编译后的Java程序的文件扩展名为.class?

a.Java的开发者认为这是一种优等(classy)语言。

b.这是对全球教师的一种巧妙赞扬。

c.任何Java程序都是一个类。

3.对象由哪两项内容组成?

a.属性和行为。

b.命令和数据文件。

c.唾液和醋。

10.10.2 答案

1.b.之所以使用extends语句,是因为子类是对超类及其超类的属性和行为的扩展。

2.c.程序至少由一个主类以及所需的其他类组成。

3.a.从某种意义上说,b也对,因为命令相当于行为,而数据文件相当于属性。

10.11 练习

如果读者不反对(object),可通过下面的练习拓展(extends)有关本章主题的知识:

创建一个 AcousticModem类,其速度为 300,且有 connect( )方法。

在有关调制解调器的项目中,在某个类中添加一个 disconnect( )方法,让各种调制解调器(电缆调制解调器、DSL调制解调器、声学调制解调器)能够断开连接。

有关为完成这些练习而编写的Java程序,请访问本书的配套网站www.java24hours.com。

没有精选讨论主题。

全部讨论主题 查看精选主题

没有讨论主题。
😃 😅 😆 😁 😂 😊 😄 😠 😩 😲 😞 😵 😰 😒 😍 😤 😜 😝 😋 😘 😚 😷 😳 😢 😭 😨 😣 😡 😌 😖 😔 😱 😪 😏 😓 😥 😫 😉 👊 👍 👆 👇 👈 👉 👋 👏 👌 👎 👐 💓 💔 💕 💖 💗 💘 💙 💚 💛 💜 💝 💞 💟