一些人用了一阵子的Java,可是对于 Java 的 package 跟 import 还是不太了解。很多人以为原始码 .java 文件中的 import 会让编译器把所 import 的程序通通写到编译好的 .class 档案中,或是认为 import 跟 C/C++ 的 #include 相似,实际上,这是错误的观念。
如果没有import
,我们在使用java类库时就需要书写该类的全路径名,例如下面代码:
java.util.ArrayList<Integer> list = new java.util.ArrayList<Integer>();
每次这样写要多敲很多字符,程序员都是很懒的,自然有人办法偷懒了,于是有了import
,只需要在java文件开头部分导入相应的类的全名一次,之后就只需要写类名就可以引用该类了,例如:
import java.util.ArrayList;
...
ArrayList<Integer> list = new ArrayList<Integer>();
上面的java.util
就是一个包,ArrayList
是该包里面的一个类,
也可以使用通配符来表示引用某个包,这样可以偷懒不少,但是尽量少这样用了。
import java.util.*;
编译时所有类名都会被替换成相应的完全路径名,如ArrayList
比替换成java.util.ArrayList
,这与我们自己书写完全路径名是一样的效果。
查找import
的类时,按照环境变量CLASSPATH
中指定的路径(如有多个,依此执行下面操作),将该路径作为根目录,然后将import
后面的完全路径名中的.
换成路径分隔符并添加.java
后缀,将根目录与替换后的路径拼接成完全路径定位要引用的类文件。例如上面的导入的java.util.ArrayList
类文件路径为$CLASSPATH/java/util/ArrayList.java
。
包用来将一组相互具有联系并组合起来完成某一功能的类聚集到一起,比如java中的工具库,通常一个库是由多个class所组成,为了方便组织我们把这组class放在同一个目录下,这个目录就是看作是一个java包(当然还需要在java文件开头用package声明一下)。
打个比方,package 名称就像是我们的姓,而 class 名称就像是我们的名字。package 名称有很多.
的,就好像是复姓。比如说 java.lang.String,就是复姓 java.lang,名字为 String 的类别;java.io.InputStream 则是复姓java.io,名字为 InputStream 的类别。
但是实际中经常会出现重名的情况,这时候就需要用不同的姓作区分,例如A写了一个String
类,B也写了个String
类,为了区分,可以通过A.String
和B.String
分别表示他们各自的String
类。按照惯例,java中习惯使用Internet域名的反序作为包名,例如我有一个域名java.oracle.com
,那么我写的String
类的包名就是com.oracle.java
。
package com.oracle.java;
public class String{
...
}
使用Internet域名反序作为包名,并非强制性,也可以使用其他名称,只要尽量保证包名唯一即可,所以常用的就是使用路径名作为包名,利用操作系统的目录层次结构作区分。例如,我写了一个String
类,放在$CLASSPATH/java/util/
目录下,那么包名就是java/util
。
package java.util;
public class String{
...
}
CLASSPATH
环境变量包含了F:/WorkDirectory/
全路径为F:/WorkDirectory/net/wuhui/util/MyString.java
的类文件,其包名应为net.wuhui.util
,这样编译器可以准确定位到MyString
这个类。
package net.wuhui.util;
public class MyString{
System.out.println("MyString");
}
测试类F:/WorkDirectory/test/Test.java
,导入上面自定义的MyString
类,并使用他它。
import net.wuhui.util.MyString;
public class Test{
public static void main(String [] args){
MyString s = new MyString();
}
}
有不正确地方,欢迎指出,万分感谢!