八宝书库 > 文学其他电子书 > Java编程思想第4版[中文版](PDF格式) >

第173部分

Java编程思想第4版[中文版](PDF格式)-第173部分

小说: Java编程思想第4版[中文版](PDF格式) 字数: 每页4000字

按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!




■条件表达式只能是boolean (布尔)类型,不可使用整数。  

■必须使用象X+Y 这样的一个表达式的结果;不能仅仅用“X+Y”来实现“副作用”。  

(8) char (字符)类型使用国际通用的16位 Unicode 字符集,所以能自动表达大多数国家的字符。  

(9) 静态引用的字串会自动转换成 String 对象。和C 及 C++不同,没有独立的静态字符数组字串可供使用。  

(10) Java增添了三个右移位运算符“》》》”,具有与“逻辑”右移位运算符类似的功用,可在最末尾插入零 

值。“》》”则会在移位的同时插入符号位(即“算术”移位)。  

(11) 尽管表面上类似,但与 C++相比,Java 数组采用的是一个颇为不同的结构,并具有独特的行为。有一个 

只读的 length 成员,通过它可知道数组有多大。而且一旦超过数组边界,运行期检查会自动丢弃一个异常。 

所有数组都是在内存“堆”里创建的,我们可将一个数组分配给另一个(只是简单地复制数组句柄)。数组 

标识符属于第一级对象,它的所有方法通常都适用于其他所有对象。  

(12) 对于所有不属于主类型的对象,都只能通过new 命令创建。和 C++不同,Java 没有相应的命令可以“在 

堆栈上”创建不属于主类型的对象。所有主类型都只能在堆栈上创建,同时不使用new 命令。所有主要的类 

都有自己的“封装(器)”类,所以能够通过 new 创建等价的、以内存“堆”为基础的对象(主类型数组是 

一个例外:它们可象C++那样通过集合初始化进行分配,或者使用 new)。  

(13) Java 中不必进行提前声明。若想在定义前使用一个类或方法,只需直接使用它即可——编译器会保证 



                                                                       672 


…………………………………………………………Page 674……………………………………………………………

使用恰当的定义。所以和在C++中不同,我们不会碰到任何涉及提前引用的问题。  

(14) Java没有预处理机。若想使用另一个库里的类,只需使用 import 命令,并指定库名即可。不存在类似 

于预处理机的宏。  

(15) Java用包代替了命名空间。由于将所有东西都置入一个类,而且由于采用了一种名为“封装”的机 

制,它能针对类名进行类似于命名空间分解的操作,所以命名的问题不再进入我们的考虑之列。数据包也会 

在单独一个库名下收集库的组件。我们只需简单地“import”(导入)一个包,剩下的工作会由编译器自动 

完成。  

(16) 被定义成类成员的对象句柄会自动初始化成null 。对基本类数据成员的初始化在Java 里得到了可靠的 

保障。若不明确地进行初始化,它们就会得到一个默认值(零或等价的值)。可对它们进行明确的初始化 

 (显式初始化):要么在类内定义它们,要么在构建器中定义。采用的语法比C++的语法更容易理解,而且 

对于 static和非 static成员来说都是固定不变的。我们不必从外部定义 static成员的存储方式,这和 C++ 

是不同的。  

(17) 在Java 里,没有象 C 和C++那样的指针。用new 创建一个对象的时候,会获得一个引用(本书一直将 

其称作“句柄”)。例如:  

String s = new String(〃howdy〃);  

然而,C++引用在创建时必须进行初始化,而且不可重定义到一个不同的位置。但Java 引用并不一定局限于 

创建时的位置。它们可根据情况任意定义,这便消除了对指针的部分需求。在C 和C++里大量采用指针的另 

一个原因是为了能指向任意一个内存位置(这同时会使它们变得不安全,也是Java 不提供这一支持的原 

因)。指针通常被看作在基本变量数组中四处移动的一种有效手段。Java 允许我们以更安全的形式达到相同 

的目标。解决指针问题的终极方法是“固有方法”(已在附录A 讨论)。将指针传递给方法时,通常不会带 

来太大的问题,因为此时没有全局函数,只有类。而且我们可传递对对象的引用。Java 语言最开始声称自己 

 “完全不采用指针!”但随着许多程序员都质问没有指针如何工作?于是后来又声明“采用受到限制的指 

针”。大家可自行判断它是否“真”的是一个指针。但不管在何种情况下,都不存在指针“算术”。  

(18) Java提供了与C++类似的“构建器”(Constructor)。如果不自己定义一个,就会获得一个默认构建 

器。而如果定义了一个非默认的构建器,就不会为我们自动定义默认构建器。这和C++是一样的。注意没有 

复制构建器,因为所有自变量都是按引用传递的。  

(19) Java 中没有“破坏器”(Destructor)。变量不存在“作用域”的问题。一个对象的“存在时间”是 

由对象的存在时间决定的,并非由垃圾收集器决定。有个 finalize()方法是每一个类的成员,它在某种程度 

上类似于C++的“破坏器”。但 finalize()是由垃圾收集器调用的,而且只负责释放“资源”(如打开的文 

件、套接字、端口、URL 等等)。如需在一个特定的地点做某样事情,必须创建一个特殊的方法,并调用 

它,不能依赖finalize()。而在另一方面,C++中的所有对象都会(或者说“应该”)破坏,但并非Java 中 

的所有对象都会被当作“垃圾”收集掉。由于 Java 不支持破坏器的概念,所以在必要的时候,必须谨慎地创 

建一个清除方法。而且针对类内的基础类以及成员对象,需要明确调用所有清除方法。  

(20) Java具有方法“过载”机制,它的工作原理与 C++函数的过载几乎是完全相同的。  

(21) Java不支持默认自变量。  

(22) Java 中没有goto 。它采取的无条件跳转机制是“break 标签”或者“continue 标准”,用于跳出当前 

的多重嵌套循环。  

(23) Java 采用了一种单根式的分级结构,因此所有对象都是从根类 Object 统一继承的。而在 C++中,我们 

可在任何地方启动一个新的继承树,所以最后往往看到包含了大量树的“一片森林”。在Java 中,我们无论 

如何都只有一个分级结构。尽管这表面上看似乎造成了限制,但由于我们知道每个对象肯定至少有一个 

Object 接口,所以往往能获得更强大的能力。C++ 目前似乎是唯一没有强制单根结构的唯一一种OO 语言。  

(24) Java没有模板或者参数化类型的其他形式。它提供了一系列集合:Vector (向量),Stack (堆栈)以 

及Hashtable (散列表),用于容纳Object 引用。利用这些集合,我们的一系列要求可得到满足。但这些集 

合并非是为实现象 C++ “标准模板库”(STL)那样的快速调用而设计的。Java 1。2 中的新集合显得更加完 

整,但仍不具备正宗模板那样的高效率使用手段。  

(25)  “垃圾收集”意味着在Java 中出现内存漏洞的情况会少得多,但也并非完全不可能(若调用一个用于 

分配存储空间的固有方法,垃圾收集器就不能对其进行跟踪监视)。然而,内存漏洞和资源漏洞多是由于编 

写不当的finalize()造成的,或是由于在已分配的一个块尾释放一种资源造成的(“破坏器”在此时显得特 

别方便)。垃圾收集器是在C++基础上的一种极大进步,使许多编程问题消弥于无形之中。但对少数几个垃 

圾收集器力有不逮的问题,它却是不大适合的。但垃圾收集器的大量优点也使这一处缺点显得微不足道。  

(26) Java 内建了对多线程的支持。利用一个特殊的Thread 类,我们可通过继承创建一个新线程(放弃了 

run()方法)。若将 synchronized (同步)关键字作为方法的一个类型限制符使用,相互排斥现象会在对象 



                                                               673 


…………………………………………………………Page 675……………………………………………………………

这一级发生。在任何给定的时间,只有一个线程能使用一个对象的synchronized方法。在另一方面,一个 

synchronized方法进入以后,它首先会“锁定”对象,防止其他任何synchronized方法再使用那个对象。 

只有退出了这个方法,才会将对象“解锁”。在线程之间,我们仍然要负责实现更复杂的同步机制,方法是 

创建自己的“监视器”类。递归的 synchronized方法可以正常运作。若线程的优先等级相同,则时间的“分 

片”不能得到保证。  

(27) 我们不是象 C++那样控制声明代码块,而是将访问限定符(public,private 和protected)置入每个 

类成员的定义里。若未规定一个“显式”(明确的)限定符,就会默认为“友好的”(friendly )。这意味 

着同一个包里的其他元素也可以访问它(相当于它们都成为C++的“friends”——朋友),但不可由包外的 

任何元素访问。类——以及类内的每个方法——都有一个访问限定符,决定它是否能在文件的外部“可 

见”。private 关键字通常很少在 Java 中使用,因为与排斥同一个包内其他类的访问相比,“友好的”访问 

通常更加有用。然而,在多线程的环境中,对 private 的恰当运用是非常重要的。Java 的protected 关键字 

意味着“可由继承者访问,亦可由包内其他元素访问”。注意 Java 没有与C++的protected 关键字等价的元 

素,后者意味着“只能由继承者访问”(以前可用“private protected”实现这个目的,但这一对关键字的 

组合已被取消了)。  

(28) 嵌套的类。在C++中,对类进行嵌套有助于隐藏名称,并便于代码的组织(但C++的“命名空间”已使 

名称的隐藏显得多余)。Java 的“封装”或“打包”概念等价于 C++的命名空间,所以不再是一个问题。 

Java 1。1 引入了“内部类”的概念,它秘密保持指向外部类的一个句柄——创建内部类对象的时候需要用 

到。这意味着内部类对象也许能访问外部类对象的成员,毋需任何条件——就好象那些成员直接隶属于内部 

类对象一样。这样便为回调问题提供了一个更优秀的方案——C++是用指向成员的指针解决的。  

(29) 由于存在前面介绍的那种内部类,所以Java 里没有指向成员的指针。  

(30) Java不存在“嵌入”(inline)方法。Java 编译器也许会自行决定嵌入一个方法,但我们对此没有更 

多的控制权力。在Java 中,可为一个方法使用 final 关键字,从而“建议”进行嵌入操作。然而,嵌入函数 

对于C++的编译器来说也只是一种建议。  

(31) Java 中的继承具有与C++相同的效果,但采用的语法不同。Java 用 extends 关键字标志从一个基础类 

的继承,并用super 关键字指出准备在基础类中调用的方法,它与我们当前所在的方法具有相同的名字(然 

而,Java 中的super 关键字只允许我们访问父类的方法——亦即分级结构的上一级)。通过在 C++中设定基 

础类的作用域,我们可访问位于分级结构较深处的方法。亦可用 super 关键字调用基础类构建器。正如早先 

指出的那样,所有类最终都会从Object 里自动继承。和C++不同,不存在明确的构建器初始化列表。但编译 

器会强迫我们在构建器主体的开头进行全部的基础类初始化,而且不允许我们在主体的后面部分进行这一工 

作。通过组合运用自动初始化以及来自未初始化对象句柄的异常,成员的初始化可得到有效的保证。  

  

public class Foo extends Bar {  

  public Foo(String msg) {  

    super(msg); // Calls base constructor  

  }  

  public baz(int i) { // Override  

    super。baz(i); // Calls base method  

  }  

}  

  

(32) Java 中的继承不会改变基础类成员的保护级别。我们不能在Java 中指定public,private 或者 

protected 继承,这一点与C++是相同的。此外,在衍生类中的优先方法不能减少对基础类方法的访问。例 

如,假设一个成员在基础类中属于 public,而我们用另一个方法代替了它,那么用于替换的方法也必须属于 

public (编译器会自动检查)。  

(33) Java提供了一个 interface 关键字,它的作用是创建抽象基础类的一个等价物。在其中填充抽象方 

法,且没有数据成员。这样一来,对于仅仅设计成一个接口的东西,以及对于用 extends 关键字在现有功能 

基础上的扩展,两者之间便产生了一个明显的差异。不值得用 abstract 关键字产生一种类似的效果,因为我 

们不能创建属于那个类的一个对象。一个 abstract (抽象)类可包含抽象方法(尽管并不要求在它里面包含 

什么东西),但它也能包含用于具体实现的代码。因此,它被限制成一个单一的继承。通过与接口联合使 

用,这一方案避免了对类似于 C++虚拟基础类那样的一些机制的需要。  

为创建可进行“例示”(即创建一个实例)的一个 interface (接口)的版本,需使用implements 关键字。 

它的语法类似于继承的语法,如下所示:  



                                                                       674 


…………………………………………………………Page 676……………………………………………………………

  

public interface Face {  

  public void smile();  

}  

public class Baz extends Bar implements Face {  

  pu

返回目录 上一页 下一页 回到顶部 0 1

你可能喜欢的