类存储在文件系统的子目录中。类的路径必须与包名匹配。

类文件也可以存储在 JAR(Java 归档)文件中。在一个 JAR 文件中,可以包含多个压缩形式的类文件和子目录,这样既可以节省空间又可以改善性能。在程序中用到第三方的库文件时,你通常要得到一个或多个需要包含的 JRE 文件。

为了使类能够被多个程序共享,需要做到下面几点:

  1. 把类放在一个目录中,例如 /home/user/classdir

    需要注意,这个目录是包树状结构的基目录。如果希望增加 com.xiang117.corejava.Employee 类,那么 Employee 类文件就必须位于子目录 /home/user/classdir/com/xiang117/corejava 中。

  2. 将 JAR 文件放在一个目录中,例如:/home/user/archives
  3. 设置类路径(class path)。类路径是所有包含类文件的路径的集合。

在 UNIX 环境中,类路径中的各项之间用冒号(:)分割:
/home/user/calssdir:.:/home/user/archives/archive.jar
而在 Windows 环境中,则以分号(;)分割:
c:\classdir;.;c:\archives\archive.jar
UNIX 和 Windows 都用点号(.)表示当前目录。

类路径包括:

  1. 基目录 /home/user/classdir 或 c:\classes。
  2. 当前目录(.)。
  3. JAR 文件 /home/user/archives/archive.jar 或 c:\archives\archive.jar。

从 Java 6 开始,可以在 JAR 文件目录中指定通配符,
/home/user/classdir:.:/home/user/archives/'*'
或者
c:\calssdir;.;c:\archives\*

在 UNIX 中,* 必须转义以防止 shell 扩展。

archives 目录中的所有 JAR 文件(但不包括 .class 文件)都包含在这个类路径中。

由于总是会搜索 Java API 的类,所以不必显示地包含在类路径中。

警告: javac 编译器总是在当前的目录中查找文件,但 Java 虚拟机仅在类路径中包含 “.” 目录的时候才查看当前目录。如果没有设置类路径,那么没有问题,因为默认的类路径会包含 “.” 目录。如果设置了类路径却忘记包含 “.” 目录,那么尽管你的程序可以没有错误地通过编译,但不能运行。

类路径所列出的目录和归档文件是搜寻类的起始点。下面看一个例子:
/home/user/calssdir:.:/home/user/archives/archive.jar
假定虚拟机要搜寻 com.xiang117.corejava.Employee 类的类文件。它首先要查看 Java API 类。显然,在那里找不到相应的类文件,所以转而查看类路径。然后查找以下文件:
 • /home/user/calssdir/com/xiang117/corejava/Employee.class
 • com/xiang117/corejava/Employee.class(从当前目录开始)
 • com/xiang117/corejava/Employee.class/home/user/archives/archive.jar 中)

编译器查找文件要比虚拟机复杂得多。如果引用了一个类,而没有指定这个类的包,那么编译器将首先查找包含这个类的包。它会查看所有的 import 指令,确定其中是否包含了这个类。例如,假定源文件包含指令:
import java.util.*:
import com.xiang117.corejava.*;
并且源代码引用了 Employee 类。编译器将尝试查找 java.lang.Employee (因为 java.lang 包总是会默认导入)、java.util.Employeecom.xiang117.corejava.Employee 和当前包中的 Employee。它会在类路径所有位置中搜索以上各个类。如果找到了一个以上的类,就会产生编译时错误(因为完全限定类名必须是唯一的,所以 import 语句的次序并不重要)。

编译器的任务不止这些,它还要查看源文件(Source files)是否比类文件新。如果是这样的话,那么源文件就被自动地重新编译。在前面已经知道,只可以导入其他包中的公共类。一个源文件只能包含一个公共类,并且文件名与公有类必须匹配。因此,编译器很容易找到公有类所在的源文件。不过,还可以从当前包中导入非公共类。这些类有可能在与类名不同的源文件中定义。如果从当前包中导入一个类,编译器就要搜索当前包中的所有源文件,查看哪个源文件定义了这个类。

1. 设置类路径

最好使用 -classpath (或 -cp,或者 Java 9 中的 --class-path)选项指定类路径:
java -classpath /home/user/classdir:.:/home/user/archives/archive.jar MyProg
或者
java -calsspath c:\classdir;.;c:\archives\archive.jar MyProg
整个指令必须写在一行中。将这样一个很长的命令行放在一个 shell 脚本或一个批处理文件中是个不错的主意。

利用 -classpath 选项设置类路径是首选的方法,也可以通过设置 CLASSPATH 环境变量来指定。具体细节依赖于所使用的 shell。在 Bourne Again shell(bash)中,命令如下:
export CLASSPATH=/home/user/classdir:.:/home/user/archives/archive.jar
在 Windows shell 中,命令如下:
set CLASSPATH=c:\classdir;.;c:\archives\archive.jar
直到退出 shell 为止,类路径设置均有效。

警告: 有人建议将 CLASSPATH 环境变量设置为永久不变的值,一般来说这是一个糟糕的想法。人们有可能会忘记全局设置, 因此,当他们的类没有正确地加载时,就会感到很奇怪。一个应该受到谴责的示例是 Windows 中 Apple 的 QuickTime 安装程序。很多年来,它都将 CLASSPATH 全局设置为指向它需要的一个 JAR 文件,而没有在类路径中包含当前路径。因此,当程序编译后却不能运行时,无数 Java 程序员不得不花费很多精力去解决这个问题。

警告: 过去,有人建议完全绕开类路径,将所有的文件都放在 jre/lib/ext 目录中。这种机制在 Java 9 中已经过时,不过不管怎样这都是一个不好的建议。很可能会从扩展目录加载一些已经遗忘很久的类,这会让人非常困惑。

在 Java 9 中,还可以从模块路径加载类。

©著作权归作者所有:来自51CTO博客作者bpx_的原创作品,如需转载,请注明出处,否则将追究法律责任

每一份赞赏源于懂得

赞赏

0人进行了赞赏支持

更多相关文章

  1. LeetCode 实战:「图解」二叉树中的最大路径和
  2. 动画:面试必刷之二叉树中和为某一值的路径
  3. 使用位运算处理一道难题:获取所有钥匙的最短路径
  4. Ansible 之 外部变量文件调用
  5. 用Python和Tableau对母婴商品销量进行数据分析(附Python源码及Tab
  6. Python处理文件的几个常用小知识
  7. centos 用户权限管理与文件权限设定 详解
  8. 有效解决U盘文件变成exe格式的方法
  9. 数据结构与算法——图最短路径

随机推荐

  1. Android设计尺寸规范--Android Design Gu
  2. Android 限定 Activity 转向
  3. androidの布局控件居于最底部实现
  4. Android 滚动Tab
  5. Android中的基本组件(2)
  6. Android TimePicker
  7. 由浅入深研究Android(3)--浅谈线程的一些东
  8. Android控件之CheckBox(复选框控件)
  9. Android中按钮点击效果显示
  10. android Content provider 组件