编程学习笔记之Java相关:包的概念和使用
来源:互联网 发布:warframe 淘宝充值 编辑:程序博客网 时间:2024/06/05 05:28
类似操作系统中的文件目录结构,Java也利用包来组织和管理类,一个包中可以包含着一些围绕某个主题的类。 包中还可以有子包,这就形成了包的层次结构。
对于类来说,类中所有成员的名字都是互不相干的,比如类A与类B中都有一个方法fun,但其实这两个fun没有任何关系。在一个Java程序的运行过程中,很可能会从Internet上下载一些类,而用户并不知晓。所以在Java中需要名字空间的完全控制,用以保证类名的唯一性。而包机制就为我们的这种目的提供了一种可能性:作为包的设计人员,可以利用包来划分名字空间以避免类名冲突,换言之,一个包中的类不能重名,但不同包中的类可以重名!。
包是一种松散的类的集合,一般不要求处于同一个包的类有明显的相互关系,如继承、包含等。由于同一个包中的类在默认情况下可以互相访问,所以为了方便管理,通常把一些在一起协同工作的类放在同一个包中。系统也是通过反映不同主题的包为用户提供不同用途的类,如输入输出类、数学运算类、Applet类等。。利用包来管理类,可以实现类库的共享和复用,类库是程序员编写Java程序的宝贵资源,是可以直接拿来使用的“程序芯片”。
包分为无名包和有名包,无名包的好处是无需对包作任何声明,可以拿来方便快捷使用,但也因为无名包没有名字,所以其它程序无法访问无名包中的类,所以说无名包只适合在局部应用。而有名包就可以被其它程序所访问,可以通过“包名.类名”访问指定包中指定的类。
在Java中,一个Java源文件被称作一个编译单元,Java的编译单元具有如下的特性:首先,一个编译单元中只能有一个public类,而该类的类名必须与该编译单元的原文件名相同,该编译单元中的其它类都是该public类的支撑类。其次,经过编译后,编译单元中的每个类都会产生一个后缀为“.class”的字节码文件,也称为类文件。最后,由一个编译单元所生成的所有类文件,肯定要归于一个包中,要么是无名包,要么是有名包。
2)包的使用
使用包【创建有名包】的关键字是package,而且package语句只能作为该Java源文件的第一条语句,而且是整个编译单元中的唯一一条package语句。该语句指定该编译单元中定义的类属于哪个包,如果默认该语句,则默认为无名包。package的使用格式如下:
package 包名; // 包名一般都用小写字母
下面我们给出一个较为具体的包使用例子:在D200_Card.Java源文件中,定义了PhoneCard类、子类NumberCard以及子子类D200_Card,在源文件的第一行用package声明了一个包,包名是cardclasses,所以该编译单元中的3个类都属于cardclasses。源文件内容如下:
package cardclasses;abstract class PhoneCard{ double balance;}abstract class Number_PhoneCard extends PhoneCard{ long cardNumber;}public class D200_Card extends Number_PhoneCard{ public D200_Card(long cn, double b){ cardNumber = cn; balance = b; } public String performDial() { balance -= 0.5; return "卡号:"+cardNumber+"\n余额:"+balance; }}根据包与目录的对应关系,cardclasses包对应的目录名应该是cardclasses,那么该目录该如何创建呢?而上面的编译单元生成的类文件又该如何存放呢?
首先我们要确定包的位置,如果我们要把cardclasses放在d:\ temp下,那么下面有两种创建包的方法:
第一种,手工创建;
首先,在Java项目开发中,应该将源文件与类文件分别放在不同的目录中,因此我们在d:\ temp目录下又新建了一个d200文件夹,用它来专门存放D200_Card.java源文件,然后在该目录下编译源文件【 D:\temp\d200> javac D200_Card.java】,执行该命令后,会在源文件所在的目录,即d200下生成3个类文件,分别是PhoneCard.class、Number_PhoneCard.class和D200_Card.class。
然后,按照我们当初对包的设计要求,需要在d:\ temp目录下创建一个与包对应的cardclasses文件夹,然后将第一步生成的3个类文件都移动到cardclasses目录下,这就相当于把类添加到包中,因为用package语句声明本编译单元中的类属于指定的包后,就必须把这些类文件放在这个包中,并且只能通过该包来访问这些类。
第二种,自动创建;
这是一种比较方便快捷的方法,它可以让编译程序在完成编译的同时,也能实现包的创建和类的塞入,该功能的编译命令如下:【D:\temp\d200>javac -d d:\temp D200_Card.java】,我们看到,与前面那个手动方式相比,这一次命令里面多了一个“-d”选项,在它后面就是指定创建包的位置,这个javac命令会根据源文件中package声明的包名,在对应的制定目录下自动创建一个与包名一样的目录,并将编译源文件后所生成的类文件全部放在这个文件夹中,完成包的创建和类的加入。当然,如果对应的包已经存在,那么javac命令会跳过创建包目录步骤,而直接将生成的字节码文件放在该已经存在的包中。如果在这个包存在一个重名的类文件,那么程序会用新的类文件替换掉已经存在的旧的类文件。最后要说明的是,如果想在特定的当前目录下创建包,那么需要使用如下命令:【D:\temp javac -d . d200\D200_Card.java】,其中里面的“.”意思就是当前目录。
最后介绍一下嵌套包的创建,以我们上面的代码为例,如果我们的package是如下使用:
package cardsystem.cardclasses; //这就是嵌套包那么编译该源文件后会创建两个包,首先是cardsystem,然后在它里面再创建一个cardclasses。
3)包的使用
将类组织成包的目的是为了更好的使用这些类,一个类要用到其它的类,无非是访问其它类的静态成员、继承这个类或创建这个类的对象并访问这个对象的属性和方法。
针对前面我们创建的cardclasses包和里面的三个类文件,我们将在这里讨论如何在包的外部访问它们。对于同一个包中的其它类,直接通过类名就可以访问,而如果是要访问其它包中public类,就需要指定被访问类所属的包了。
我们首先在d:\temp下建立一个测试程序:
public class TestPackage{ public static void main(String args[]) { D200_Card my200 = new D200_Card(11111111, 50); System.out.println(my200.performDial()); }}但是上面的代码连编译都无法通过:“找不到D200_Card类”,这是因为D200_Card类文件并没有在当前的无名包中,程序也没有指明这个类文件在什么地方,所以编译会报错,改成如下形式即可:
public class TestPackage{ public static void main(String args[]) { cardclasses.D200_Card my200 = new cardclasses.D200_Card(11111111, 50); System.out.println(my200.performDial()); }}虽然这种方法是可行的,但实际应用时却很麻烦,因为我们要在每次使用D200_Card类时都要在前面加上cardclasses,这样非常不方便。所以流行的解决方式是使用下面这种方法:
import cardclasses.D200_Card; //这样就引入了需要使用的D200_Card类public class TestPackage{ public static void main(String args[]) { D200_Card my200 = new D200_Card(11111111, 50); System.out.println(my200.performDial()); }}甚至我们可以直接引入整个包:
import cardclasses.*; //引入了整个包,“*”意味着包中所有的类public class TestPackage{ public static void main(String args[]) { D200_Card my200 = new D200_Card(11111111, 50); System.out.println(my200.performDial()); }}需要注意的是,在一个编译单元中,import不限于一个,但它们必须要出现在所有的类定义之前!此外,import语句仅仅是将指定包中的类引入到当前的类名空间,就是告诉编译程序去哪儿找程序中要使用的类,import语句并不加载类的定义,也不会对那些类文件产生不好的影响。
当引入的不同包中有类重名的情况时,为区分使用的是哪个包中的类,在类名前加上包名最前缀。在import语句中,包名部分也可以包含小数点,如【import Java.awt.*;】,这句话的意思是:引进Java包中的awt子包中的所有类。
最后还要讲一下包的定位,包放在哪个目录下可以由程序员自由指定,虽然在程序中可以通过多种方法指定包的位置,但系统又该到什么地方查找这个包呢?这就牵扯到环境变量CLASSPATH了。
CLASSPATH就像操作系统中的PATH,它指明了查找包的路径,系统将环境变量CLASSPATH包含的一个或多个目录作为起始目录来查找包目录,并在找到的包目录下查找类文件。
例如我们可以在命令方式下这样设置CLASSPATH环境变量:【 set CLASSPATH = .;d:\temp 】,这样将会为系统设置了两个查找包的途径:第一是查看当前目录下是否有程序需要的包,第二是查看【d:\temp】目录下是否有程序需要的包。
- 编程学习笔记之Java相关:包的概念和使用
- 编程学习笔记之Java相关:接口(interface)的概念与使用
- Java学习笔记之断言的相关机制和使用
- 编程学习笔记之Java相关vector向量的介绍
- java学习笔记之环境的配置及其相关概念的解释
- java 包概念和包之间的访问学习实录
- 网络编程相关概念学习笔记
- Oracle 学习笔记之包的使用
- 编程学习笔记之java相关::内存回收原理
- 编程学习笔记之c++相关::模板元的学习
- golang学习笔记-包的概念
- Java学习笔记之包
- 学习笔记之开发相关概念(2)--内网和外网
- 学习笔记之开发相关概念(3)--项目部署和项目发布
- 学习笔记之开发相关概念(5)--大数据和人工智能
- JAVA与模式学习笔记之关系的概念
- Java学习之网络编程--概念
- IOS学习笔记(六)之UISlider的概念和使用方法
- 【hibernate】 hibernate 注解之 SequenceGenerator
- 如何在一台windows主机上搭建mysql主从复制
- 套接字I/O
- Mybatis分库分表扩展插件
- LeetCode 318. Maximum Product of Word Lengths
- 编程学习笔记之Java相关:包的概念和使用
- tiles3 & spring
- openstack neutron(tap、qvb、qvo)介绍
- AAC的各种规格
- 【WC2017模拟1.22】简单题
- springboot 事物管理
- C/C++的编译过程中到底发生了什么?
- 最大公约数-GCD The Largest
- 20170123 Coursera Stanford-MachineLearning/Week7