-- 作者:admin
-- 发布时间:2006/2/26 21:41:18
-- 课件13下载——Java的包
利用Java的包可以更加有效的对类进行管理。
1、简介 一般而言,Java程序文件在编译后,默认总是在当前目录生成字节码文件,同样,如果Java程序文件要调用其他自定义类生成对象,也总是在当前目录中寻找这些类(系统类除外)。这就说明,当前目录是一个Java类的默认容器,可以存放所有Java程序的自定义类,这个默认容器通常也被称为“包”。
2、包的使用 2、1 包的定义 要想改变Java类默认的所在包,可以通过package语句显式的定义包,如: package myJava;
public class cls { private int val=0; public void setVal(int v) { this.val=v; } public int getVal() { return val; } }
注意:编译含有包的文件需要写入正确的语法,如: javac -d . cls.java 其中,-d表示javac程序的命令行参数,意思是指将所生成的包放于指定目录中,“.”表示当前目录。
编译后,就会发现在当前目录下生成一个名称为myJava的目录,而生成的字节码文件位于其中。
如果想把包文件放入其他目录,可以用-d参数来定义,如: javac -d d:\\ cls.java
包的结构有时也可以嵌套较多,如: package myJava.exec;
public class cls { private int val=0; public void setVal(int v) { this.val=v; } public int getVal() { return val; } } 编译后,就会发现在当前目录下生成一个名称为myJava的目录,里面还有个名称为exec的目录,而生成的字节码文件位于其中。
说明:package语句是Java语言中的定义包的基本语句,它的层次是通过目录的形式来表达的,通过这种方式,人们就可以将自定义类放入一个指定的包下。
2、2 包的导入 要想使用一个不位于当前默认包下的类文件,就需要在使用前将类文件的所在包导入,如: import myJava.exec.cls;
public class exec { public static void main(String args[]) { cls c=new cls(); System.out.println(c.getVal()); } }
编译、执行方法与处理一般程序文件无异,为: javac exec.java java exec
说明:类前面的包名称能够指引Java找到这个类,但是它也只是在当前路径下查找,如果包不在当前路径下,就需要通过另外一个javac程序的参数-classpath来指定包所在的物理路径,如编译方法: javac -classpath d:\\ exec.java
运行方法稍有不同 如书写:java exec,报错为:NoClassDefFoundError: myJava/exec/cls,说明运行时仍然需要找到包,仍然需要指定包的物理路径。 如书写:java -classpath d:\\ exec,报错为:NoClassDefFoundError: exec,说明它无法找到当前程序,因为-classpath已经被完全设置为非当前路径,所以正确的写法是也要将包含当前程序的路径(即当前路径)加上,如: java -classpath d:\\;. exec 注意:两个路径通过“;”分割。
也可以在使用类的同时,直接指定类的所在包,如: public class exec { public static void main(String args[]) { myJava.exec.cls c=new myJava.exec.cls(); System.out.println(c.getVal()); } }
说明:如果将生成的类包放入一个特殊目录,即可不用指定classpath即可编译和运行,这个目录为<JSDK>\\jre\\classes(可能开始没有被创建,新建之即可) 步骤为: 1)javac -d . cls.java 2)将包目录拷贝至<JSDK>\\jre\\classes 3)javac exec.java 4)java exec
注意:如果这一步存在问题,请检查path路径是否正确(最好只是设置为当前J2SDK的工作目录,即<JSDK>\\bin,以防止其他JVM的干扰),或者检查classpath的设置(确认是否为.,以防止其他路径下的类产生干扰)
2、3 多个包的导入 反复使用import语句就能够将更多不同包中的类导入当前程序,如: 一个类: package myJava.exec;
public class cls { private int val=0; public void setVal(int v) { this.val=v; } public int getVal() { return val; } }
另外一个类: package exec;
public class othercls { private int val=1; public void setVal(int v) { this.val=v; } public int getVal() { return val; } }
使用上述两个类的程序为: import myJava.exec.cls; import exec.othercls;
public class exec { public static void main(String args[]) { cls c=new cls(); System.out.println(c.getVal()); othercls oc=new othercls(); System.out.println(oc.getVal()); } }
输出为: 0 1
但是有时也会出现问题,如: 一个类: package myJava.exec;
public class cls { private int val=0; public void setVal(int v) { this.val=v; } public int getVal() { return val; } }
另一个类: package other;
public class cls { private int val=1; public void setVal(int v) { this.val=v; } public int getVal() { return val; } }
使用上述两个类的程序为: import myJava.exec.cls; import other.cls;
public class exec { public static void main(String args[]) { cls c=new cls(); System.out.println(c.getVal()); } }
编译报错为:myJava.exec.cls is already defined in a single-type import,意思是说cls这个类已经在myJava.exec包中导入过了,不能再次从other包中导入同名类。其实纵然可以同时导入,程序内部的cls类又会是哪个包中的cls类呢?显然,对于不同包中的同名类不能这样使用。不过,可以采用在类前加上包前缀的方法来实现预期目的,如: public class exec { public static void main(String args[]) { myJava.exec.cls c1=new myJava.exec.cls(); System.out.println(c1.getVal()); other.cls c2=new other.cls(); System.out.println(c2.getVal()); } }
此时,可以看出Java使用包来管理类是具有很多优势的,如 1)首先,对于类文件来说,可以通过包进行更加有效的分类管理,避免将许多类放入同一个目录所带来的混乱。 2)其次,如果一个程序需要使用外部的多个同名类,也可以通过不同的包来限定具体的类。当然,此时的包名称不能再重复了。事实上,一般对于包的起名往往采用本地主机网络域名逆写的方式来表达,如: package cn.edu.njue; 由于本地主机的网络域名具有唯一性,所以不同编程者生产的类一般不会具有同名包。
考虑下面的情况: 类文件: package myJava.exec;
public class cls { private int val=0; public void setVal(int v) { this.val=v; } public int getVal() { return val; } }
使用该类的文件: package cn.edu.njue;
public class exec { public static void main(String args[]) { myJava.exec.cls c1=new myJava.exec.cls(); System.out.println(c1.getVal()); } }
编译完上述两个类后,会发现当前目录下存在两个目录,没有字节码文件,那么如何运行exec类呢? 直接进入exec所在路径不是办法,因为那样将无法获取cls类。运行exec的正确做法为: 还在当前路径下,指令为: java cn.edu.njue.exec
2、4 特殊的包形式——jar文件 包除了展示为目录结果以外,它也可以使用文件的形式来展示,这种文件为jar文件(Java Archive File)。它是压缩文件(ZIP格式,可以使用WINRAR或者WINZIP打开),里面既含有目录结构,也含有相关字节码文件。
如下例: 类文件为: package mypack;
public class cls { public int val=0; }
使用该类的文件为: import mypack.cls;
public class exec { public static void main(String args[]) { cls c1=new cls(); System.out.println(c1.val); } }
制作方法为: 1)首先,对于上述程序,先将cls类生成字节码文件,指令为:javac -d . cls.java 2)其次,将上述包和字节码文件打包为jar文件,指令为:jar cvf mypack.jar mypack/*.class 屏幕输出为: 标明清单(manifest) 增加:myJava/exec/cls.class(读入= 351) (写出= 251)(压缩了 28%)
观察当前目录,会发现一个jar文件,用解压缩软件打开看看,会发现里面有目录结构和字节码文件,同时还有个系统使用的清单文件。 3)对于生成的jar文件,可以将其放入<JSDK>\\jre\\lib\\ext下,这时就可以直接编译使用该包的其他文件,Java会自动调用,如: javac exec.java java exec
注意:如果这一步存在问题,请检查path路径是否正确(最好只是设置为当前J2SDK的工作目录,即<JSDK>\\bin,以防止其他JVM的干扰),或者检查classpath的设置(确认是否为.,以防止其他路径下的类产生干扰)
3 friendly类型 一个例子: 类文件为: public class cls { int val=0; //attention! }
使用该类的文件为: public class exec { public static void main(String args[]) { cls c1=new cls(); System.out.println(c1.val); } }
输出为: 0
再看一个例子: 类文件为: package myJava.exec;
public class cls { int val=0; }
使用该类的文件为: import myJava.exec.cls;
public class exec { public static void main(String args[]) { cls c1=new cls(); System.out.println(c1.val); } } 编译报错为: val is not public in myJava.exec.cls; cannot be accessed from outside package
说明:在Java文件中,如果没有在类成员前加上访问修饰符,默认为friendly类型,这种类型修饰的成员只能由同一个包中的其他类直接访问,而不在同一个包中的其他类就不能直接访问。显然,上例中exec和cls是在两个不同的包中。
注意:这种访问修饰符无需显式写入,默认即为。
4)Java的系统包 Java系统提供的系统类库文件皆位于指定的某个包,这些包全部压缩成了一个jar文件,为<JSDK>\\jre\\lib\\rt.jar文件(可以打开看看,全部都是位于不同包的字节码文件)。原始的类库源代码放在<JSDK>\\src.zip文件中(可以打开看看,全部都是源代码文件,值得好好学习)。
一般而言,若要使用这些包中的类也要显式的导入,但是对于lang包中的内容无需显式导入也可以使用,因为该包中包含的类是Java编程语言设计的基础,所以系统自动导入。
其中比较重要的类包括:Object(类体系结构的根)、Class(封装对象或接口运行时的状态)、封装类(封装基本数据类型,为基本数据类型建立对象表达式)、Void类(有一个TYPE域,该域保存对类型void的Class对象的引用)、Math类(提供一些常用的数学运算的方法)、String和StringBuffer(提供常用的字符串运算)以及提供“系统操作”的类(如ClassLoader、Process、Runtime、SecurityManager、System等,功能为管理类的动态加载、外部进程的创建、主机环境查询及安全策略的执行等)。
其他的一些常见包及其功能为:java.io(这个包由对您的输入/输出操作有用的类组成)、java.applet(该包由您在浏览器中执行一个applet所需要的类组成)、java.awt(该包对创建GUI应用程序有用)、java.util(该包提供了许多创建如lists, calendar, date等所需要的类和接口)、java.net(该包提供了许多进行TCP/IP网络编程的类和接口)等。
[此贴子已经被作者于2010-12-12 07:41:58编辑过]
|