《JAVA深度历险》札记(五)package和import机制
关于包知识的一些总结
事实上,几乎大多数版本的 JDK 都会于安装时主动在\system32 底下复制 一份 java.exe,而\system32 通常又是 Windows 默认 path 环境变量中的其中一个路径,所以一般的情况下,都会发生可以执行 java.exe,却不能执行 javac.exe 的情形。
结论一:
如果您的类属于某个package,那么您就应该将它至于该package所对应的相对路径之下。举例来说,如果您有个类叫做C,在xyz.pqr.abc包下,那么您就必须建立一个三层的目录xyz\pqr\abr,然后将C.java或是C.class放置到这个目录下,才能让javac.exe 或是java.exe顺利执行。
结论二:
当您使用javac.exe 编译的时候,类.java文件的位置一定要根据结论一所说来放置,如果该.java文件出现在不该出现的地方,除了很容易造成混淆不清,而且有时候抓不出编译为何发生错误,因为javac.exe 输出的错误信息根本无法改善问题。
结论三:
编译时,如果程序里用到其他的类,不需要该类的.java文件也一样能够通过编译。
结论四:
当使用javac.exe 编译程序却又没有该类的.java文件时,类字节码放置的位置应该根据结论一所说的方式放置。如果类字节码出现在不该出现的地方,有很大的可能性会造成难以的编译错误。这样做,除了没有意义之外,还随时都有可能造成您的困扰。
结论五:
当使用javac,java指令时,他们会自动把当前需要编译/运行的类的目录作为搜索的根目录,假如需要另外的目录,就需要用-classpath指令指定。
在实际生活中,只要和Java 程式语言相关的工具,都会和package 与 import 机制息息相关。比方说如果您开发 MIDlet,必定会用到preverify.exe;如果要使用JNI,您就会用到javah.exe,使用这些工具时如果您没有遵循package与import 机制的运作方式,可是无法得到您要的结果。
编译时期(Compile-time)的Package 运作机制
不管你有没有使用import指令,存在目前目录下的类都会被编译器优先采用,只要它不属于任何package。这是因为编译器总是先假设您所输入的类名称就是该类的全名(不属于任何package),然后从-classpath 所指定的路径中搜寻属于该类的源码或.class 文件。
当java 编译器开始编译某个类的源文件时,首先他会作一件事情,就是建构类路径参考表。
载入类的过程:
package解析过程:
就是当编译器找到该类的.class文件或源码之后,都会加以验证他们使否真的属于这个package,如果有问题,编译器一样会发出错误讯息;但是如果并非透make(自动解析名称,自动编译所需类)机制来编译程式,是不会做这项验证工作的。
两个误解:
1. import 和C/C++里的include同意义。
2. 在import里使用万用字元,如import xy* ,会让编译器效率减低。
真相:
1、在Java 里头,import 应该和C/C++里的namespace 等价才对,而非一般所说的include。
2、类路径参考表里的资料,只是单纯拿来合成,让编译器可以很快地定位到类.class文件或源码的位置,并不会递回式地帮我们自动搜索该路径底下其他的类,所以不管在import处使用完整的类名称或.*,即使原码会使得类路径参考表和相对类参考表很大很大,但是javac.exe 内部在处理这些资料表格时也是采用HashTable 的设计,所以对编译速度的影响几乎微乎其微。
Java 的动态连结本质
这种方式与传统的程式语言有很大的不同,一般的程序语言在最后都是将所有的程序static link至同一个执行档(.exe)之中,如果要做到动态抽换功能模组的的话,就必须借助动态链接库Windows 上为DLL,UNIX 上为shareobject)。但是,在Java 之中,每一个类所构成的类.class我们都能将它视为动态链接库。
执行时期(Run-time)的 Package 运作机制