这才是Java用 package的名字寻找cass文件的地方。(此外,它还 会根据Java解释器所在的位置查找一些标准目录。) 为了能讲得更清楚,就拿我的域名 bruceeckel,com举例。它倒过来 就是 com bruceeckel,这样我写的类就有了全球唯一的名字了。(过 去,com,edu,org这些扩展,在Java的 package名字里面是要大 写的,但是Java2作了改进,所以现在 package的名字都是小写的。) 我还可以进一步分下去,创建一个名为 simple的类库,所以 package 的名字是 现在,你就能用这个 package的名字来管下面这两个文件了 //: com: bruceeckel: simple: Vector. java // Creating a package package com. bruceeckel simple public class Vector public Vector()I System. out. println("com. bruceeckel simple Vector")i }///:~ 等到你要自己写 package的时候,你就会发现, package语句必须是 文件里的第一个非注释行。第二个文件看上去非常相似 com: bruceeckel: simple: List. java // Creating a package package com. bruceeckel simple ublic class list public List()t System. out. println("com. bruceeckel simple. List")i }///:~ 在我的机器上这两个文件都放在这个子目录里 C: \DOC\Javar\com\bruceeckel\simple 第6页共23页 www.wgqgh.com/shhgs/tij.html email:shhes@sohu.com
Chapter 5: Hiding the Implementation 第 6 页 共 23 页 www.wgqqh.com/shhgs/tij.html email: shhgs@sohu.com 这才是 Java 用 package 的名字寻找.class 文件的地方。(此外,它还 会根据 Java 解释器所在的位置查找一些标准目录。) 为了能讲得更清楚,就拿我的域名 bruceeckel.com 举例。它倒过来 就是 com.bruceeckel,这样我写的类就有了全球唯一的名字了。(过 去,com,edu,org 这些扩展,在 Java 的 package 名字里面是要大 写的,但是 Java 2 作了改进,所以现在 package 的名字都是小写的。) 我还可以进一步分下去,创建一个名为 simple 的类库,所以 package 的名字是: package com.bruceeckel.simple; 现在,你就能用这个 package 的名字来管下面这两个文件了: //: com:bruceeckel:simple:Vector.java // Creating a package. package com.bruceeckel.simple; public class Vector { public Vector() { System.out.println("com.bruceeckel.simple.Vector"); } } ///:~ 等到你要自己写 package 的时候,你就会发现,package 语句必须是 文件里的第一个非注释行。第二个文件看上去非常相似: //: com:bruceeckel:simple:List.java // Creating a package. package com.bruceeckel.simple; public class List { public List() { System.out.println("com.bruceeckel.simple.List"); } } ///:~ 在我的机器上这两个文件都放在这个子目录里: C:\DOC\JavaT\com\bruceeckel\simple
Thinking in Java 3Edition 只要看一遍这个路径,你就会发现 package的名字 com. bruceeckel. simple,但是这个路径的前面部分又是什么呢?这 是由 CLASSPATH环境变量控制的,在我的机器上,它是: CLASSPATH=iD: \JAVA\LIB; C: \DOC\JavaT 你会看到 CLASSPATH可以有好几个可供选择的搜索路径 但是,使用JAR文件的时候会有一点变化。除了要告诉它该到哪里去找 这个JAR文件,你必须将文件名放到 CLASSPATH里面。所以对名为 grape.Jar的JAR来说, CLASSPATH应该包括 CLASSPATH=; D: \JAVA\LIB; C: \flavors\grape. jar 设完 CLASSPATH之后,下面这个文件就可以放在任何目录里了 //: c05: LibTest java / Uses the lib import com. bruceeckel. simpletest. import com. bruceeckel simple public class LibTest static Test monitor new Test( public static void main(String[] args) i Vector v new Vector(i monitor. expect(new String[] le vector " com. bruceeckel simple List }/// 当编译器碰到了 simple类库的 import语句的时候,它就开始在 CLASSPATH所给出的目录下搜索,先找com\ bruceeckel\simple子 目录,再找编译后的文件( Vector就找 Vector class,List就找 List class)。注意 Vector和List类,以及其中要用的方法都必须是 public的。 对Java的初学者来说,设置 CLASSPATH曾经是一桩非常棘手的事(至 少我开始的时候是这样的),所以Sun在Java2的JDK里面作了一些改 进,让它变得稍微智能一些。你会发觉安装之后,即使不设置 CLASSPATH,它也能编译和运行一些基本的Java程序。然而要编译和 第7页共23页 www.wgqqh.com/shhgs/tij.html emailshhgs@sohu.com
Thinking in Java 3rd Edition 第 7 页 共 23 页 www.wgqqh.com/shhgs/tij.html email: shhgs@sohu.com 只要看一遍这个路径,你就会发现 package 的名字 com.bruceeckel.simple,但是这个路径的前面部分又是什么呢?这 是由 CLASSPATH 环境变量控制的,在我的机器上,它是: CLASSPATH=.;D:\JAVA\LIB;C:\DOC\JavaT 你会看到 CLASSPATH 可以有好几个可供选择的搜索路径。 但是,使用 JAR 文件的时候会有一点变化。除了要告诉它该到哪里去找 这个 JAR 文件,你必须将文件名放到 CLASSPATH 里面。所以对名为 grape.jar 的 JAR 来说,CLASSPATH 应该包括: CLASSPATH=.;D:\JAVA\LIB;C:\flavors\grape.jar 设完 CLASSPATH 之后,下面这个文件就可以放在任何目录里了: //: c05:LibTest.java // Uses the library. import com.bruceeckel.simpletest.*; import com.bruceeckel.simple.*; public class LibTest { static Test monitor = new Test(); public static void main(String[] args) { Vector v = new Vector(); List l = new List(); monitor.expect(new String[] { "com.bruceeckel.simple.Vector", "com.bruceeckel.simple.List" }); } } ///:~ 当编译器碰到了 simple 类库的 import 语句的时候,它就开始在 CLASSPATH 所给出的目录下搜索,先找 com\bruceeckel\simple 子 目录,再找编译后的文件(Vector 就找 Vector.class,List 就找 List.class)。注意 Vector 和 List 类,以及其中要用的方法都必须是 public 的。 对 Java 的初学者来说,设置 CLASSPATH 曾经是一桩非常棘手的事(至 少我开始的时候是这样的),所以 Sun 在 Java 2 的 JDK 里面作了一些改 进,让它变得稍微智能一些。你会发觉安装之后,即使不设置 CLASSPATH,它也能编译和运行一些基本的 Java 程序。然而要编译和
Chapter 5: Hiding the Implementation 运行本书的源代码(可以从www.BruceEcke!com下载),你就必须将这 些代码的根目录加到 CLASSPATH里面。 冲突 如果两个“*”所引入的类库都包括一个同名的类,那又会怎样呢?举例 来说,假设有个程序 import com. bruceeckel simple.*i import java.util.*i 由于 java. util.*也包括了一个 Vector类,因此这就有可能会引发冲 突。然而,只要你不写会引起冲突的代码,一切会OK——这种做法很 好,因为不然的话,你得为了避免根本不可能发生的冲突而多写很多代 码 但是如果你要创建一个 Vector的话,冲突就真的会来了: Vector v= new vector o 你指的是那个 Vector类呢?编译器不知道,读代码的人也不知道。所以 编译器就报错了,它会要你明确地指明这是哪个类。比方说,如果我要使 用Java标准的 Vector,我就必须说: java util. Vector v new javautil. Vector()i 由于这种写法(再加上 CLASSPATH)已经能完全指明 Vector的位置 了,因此除非你还要使用 java. util的其它类,否则就不必再使用 import java.util*。 一个自定义的工具类库 有了这些知识,你就能创建你自己的工具类库以减少甚至彻底消除重复代 码了。假设我们要为 System. out. printin()创建一个别名以减少打 字的量。这可以是 tools package的一部分 com: bruceeckel: tools: P java / The P rint P. rintln shorthand package com. bruceeckel. tools; public class P public static void rint(string s)t 第8页共23页 www.wgqgh.com/shhgs/tij.html email:shhes@sohu.com
Chapter 5: Hiding the Implementation 第 8 页 共 23 页 www.wgqqh.com/shhgs/tij.html email: shhgs@sohu.com 运行本书的源代码(可以从 www.BruceEckel.com 下载),你就必须将这 些代码的根目录加到 CLASSPATH 里面。 冲突 如果两个“*”所引入的类库都包括一个同名的类,那又会怎样呢?举例 来说,假设有个程序: import com.bruceeckel.simple.*; import java.util.*; 由于 java.util.* 也包括了一个 Vector 类,因此这就有可能会引发冲 突。然而,只要你不写会引起冲突的代码,一切会 OK——这种做法很 好,因为不然的话,你得为了避免根本不可能发生的冲突而多写很多代 码。 但是如果你要创建一个 Vector 的话,冲突就真的会来了: Vector v = new Vector(); 你指的是那个 Vector 类呢?编译器不知道,读代码的人也不知道。所以 编译器就报错了,它会要你明确地指明这是哪个类。比方说,如果我要使 用 Java 标准的 Vector,我就必须说: java.util.Vector v = new java.util.Vector(); 由于这种写法(再加上 CLASSPATH)已经能完全指明 Vector 的位置 了,因此除非你还要使用 java.util 的其它类,否则就不必再使用 import java.util.*。 一个自定义的工具类库 有了这些知识,你就能创建你自己的工具类库以减少甚至彻底消除重复代 码了。假设我们要为 System.out.println( ) 创建一个别名以减少打 字的量。这可以是 tools package 的一部分: //: com:bruceeckel:tools:P.java // The P.rint & P.rintln shorthand. package com.bruceeckel.tools; public class P { public static void rint(String s) {