您的位置:首页 > 编程语言 > Java开发

package用法

2015-08-25 17:36 555 查看
java应用程序文件

这个说法是我自己抽象出来的,指的是一般的组织在package中的所有文件。

大体分成这三种:

1,java程序源文件,扩展名为.java。

2,编译好的java类文件,扩展名为.class。

3,其他文件,除了以上的,就是资源文件。

例如图片文件,xml文件,mp3文件

等等等等都可以组织在package之中。(你当然也可以把一部电影放在package里面,当然

不提倡这样做)

package干吗用?

package就是组织文件的一种方式。

最大的作用就是组织java类文件。

成千上万的class文件,总难免重名吧,即便不重名,那么多你记得住么?当然要分门别类

的组织起来方便你随时取用吧,这个就是package最大的作用。

package是个什么东西?

package本身是一个比较抽象的逻辑概念,它的宗旨是将东西组织在一棵树里面,就好像

linux的文件系统一样,它有一个根,然后从根开始有目录和文件,然后目录中也可以有

目录。而实现的时候是怎样的呢?是利用文件系统的目录结构或者利用压缩文件中的目录

结构来组织的。

package怎么实现的?

首先讲其最重要的应用——组织源代码。

我们知道java源代码的基本单元是一个.java文本文件。

一个.java文件可以包含一个public类和无数包级类,

默认什么访问修饰都没有的类就是一个包级类。这种类只能在本package中使用。

当然了,类当中还可以有类,名唤内隐类,内隐类的访问修饰就可以是protected

或者甚至是private了。

好,那么何谓本package呢?

当你在源代码的最开头(当然,注释可以放在更开头的位置)不写package语句的话,那么

当前编译单元中的所有编译出来的类就只能够放在package的"/"上,这种package我们叫做

default package。一般我们写个HelloWorld或者简单调几个api实现个小功能的话,一般

采用这种“不打包”似的default package就可以了。

但是,当你的类开始泛滥起来的时候,你就必须考虑给类打个包放在某个package中了。

方法很简单,在所有代码开始之前写一句

package 包名;

即可。

包名是用"."间隔的字符串,一般能够当作文件名的字符串就能用到这里来。

比如

package aaa.bbb.ccc;

意味着这个编译单元所编译出来的class都必须放在/aaa/bbb/ccc这个目录之下。

否则这种类就无法正常使用,正是这种机制保证了类的严格组织。

实际上,当你在编译一些有package语句的编译单元的时候,如果你使用的是命令行的话,

应该使用-d参数让编译器自己生成目录结构,实际上你的.java就应该放在这种目录结构

之中。我举个非常简单的例子,有个人写了这么两个.java文件。

/*   A.java */

package aaa.bbb.ccc;

public class A{

    B b=new B();

}

/* B.java*/

package aaa.bbb.ccc;

public class B{}

然后这个人就把这两个文件就放在当前目录之下,然后javac A.java,

然后傻眼。

说找不到B,怎么找不到呢?

为什么找不到呢,不是在一个package里面吗?

对,是在一个package里面,但是B.java必须放在当前目录/aaa/bbb/ccc下面才可用,

当javac编译A.java的时候,它发现当前所在的包是aaa.bbb.ccc,然后需要一个B类,

没有B.class,就要去找B.java,而B.java的package语句和自己所在目录结构不符,没法

使用,所以就傻眼了。

这个人就知道了把B.java放到当前目录/aaa/bbb/ccc里面,嘿,编译通过了。

没错,生成了A.class,但是A.class还是不可用的,因为它不在它应该在的地方。

我们又必须将它放到它应该在的地方,它才能好好运作。

那你说我把A.java也放在当前目录/aaa/bbb/ccc里面,然后

javac aaa.bbb.ccc.A.java

漂亮吧?

不行,为什么?因为javac接受的参数是一个文件系统的文件名,javac命令行中的参数

只能是一个完整的路径名。

那我把A.java放在当前目录/aaa/bbb/ccc里面,然后

javac aaa/bbb/ccc/A.java

这下好了吧,恩,差不多,但是生成的class还是直接丢在了源代码目录之下

最好是

javac -d bin aaa/bbb/ccc/A.java

这样就会在当前目录的bin目录下看到完整的目录结构以及放置妥当的class文件。

package与classpath不得不说的事

讲了半天还是觉得不太清楚package的"/"到底在哪里,在当前目录吗?

如果不知道package的"/"在哪里,那那些package中的文件在哪里就更无从得知了。

回答很简单,package的"/"在classpath中。

头痛了,package没有搞懂的,classpath一般也不会很懂。

没事,classpath说白了就是一堆path,这些该死的path有的指向一个目录,有的指向一个

文件(只能是zip或者jar两种,当然更保险的话还是用jar比较好)。

对于java虚拟机而言,它并不想过问这些path的八卦,它所做的是一视同仁!

它要的是所有这些path中的内容,对,对它而言,它不在乎内容是来自一个目录还是来自

一个文件,总而言之,所有的这些东西在他眼里都一样。就好像它空出一块地方,把所有

的文件解压,把所有的目录中的内容保留目录结构的送入相应位置,形成一套它自己感

兴趣的package组织方式。它要的就是这种方式来访问。

所以我可以在a.jar中有一个目录结构aaa/bbb/ccc/A.class,然后在b.jar中也有一个同样

的目录结构aaa/bbb/ccc/B.class。当我把这两个文件都放在classpath中的时候,

对虚拟机而言,这个A.class和这个B.class就是放在同一个package中的。

前面的那个实践也透视了这一点,实际上编译A.java的时候,是在classpath中寻找class

文件的,找不到,则会在sourcepath中寻找其源代码文件(不设定的话,sourcepath就是等

于classpath),当我们把B.java放在当前目录中合适的目录结构中的时候,它就会找到

这个文件并将它编译,然后进行使用。因为当前目录"."是在classpath中的。

原则就是,对java而言,它是忽略文件系统细节的,它要求的只是自己的classpath

中按照约定存放的资源。

(以上classpath对应的classloader是app classloader)

import干吗用的?

java几乎所有的api都是用java语言本身写成的,是的,那些你所经常使用的String,

HashSet,HashMap等等这些类都是用java语言写成的。

这些类的制作是我们也可以来做的事情,他们同样是写出一个个java文件,打上不同的

package,然后编译好,最后压缩一下,成为jre里面的dt.jar之类的文件,变成了我们常

常调用的库。

有的人以为,当我们写下import java.util.*;之前,我们的这些库就是“不可达”的,

而当我们写下了import java.util.*之后,我们所需要的那个库文件就会被某种不知道的

机制加入到我们的工程。

错!这些人是纯粹打死不看书的想当然类型,只在乎自己的意象,不在乎其所以然。

不管你写还是不写import语句,对当前外部的编译和执行环境都不会有任何的影响。

即便你不写import java.util.*;

你照样可以用java.util.HashMap来调用系统api,根本不用做更多的事情。

这里我不得不再提一次,不要把dt.jar放到CLASSPATH环境变量中,它已经在classpath中

了,而且此举常常让初学者丢掉了默认在classpath中的"."当前目录,让他们一番热情学

java写helloworld的火焰被一盆水扑灭。

import有啥用的呢?

它只不过是一种让你少打点字的方法,就跟c++的名称空间的using语句功能一样,就是暴

露那个package下面所有的类,写代码的时候就可以直接写类名,而不用写下完整的

包名.类名,仅此而已。

不得不提的是,*仅仅代表类名,不负责以下更深层次中各级目录中的东西。

import java.*;实际上没有暴露任何类,因为没有类是打在这个包里面的。它没有

暴露java.util.*,也没有暴露java.sql.*等等,它仅仅暴露了java目录下面所有的类。

打包成jar文件

一般的打包成jar文件,除了将目录结构压缩存储在一个zip格式但是扩展名比较畸形的

文件中之外没有做任何事情。

jar文件可以用任何能够解压zip的工具来解压,如果你讨厌使用jar命令行,你甚至可以

直接使用winrar来压缩,然后改个名字即可。

当然了,jar文件也有别的用处,比如“可直接执行的jar”。

“可直接执行的jar”跟“不可直接执行的jar”的区别仅仅在于它多了一个配置文件在

jar文件中,这个文件中指出了一个完整的类名,告诉java.exe或者javaw.exe,main方法

这个类里面而已。

欲知道更多关于jar文件的用法,请参考精华区。

贴二——package从实践到理论:

package就是catalog,所谓目录册。

什么是目录册呢?比较抽象的说,就是让你快速定位一个东西的册子。

比如电话簿,比如字典,比如搜索引擎。

java中,主要是class文件,当然也可以是任何别的文件,就是通过package来组织的。

package有点类似一个虚拟的文件系统,可以将所有的东西组织在树形结构之中。

这有一个根"/",也就是我们什么package语句都不写的情况下class文件所应该处的位置。

直接赤裸裸放在classpath中的东西都是放在"/"下面,然后如果有package语句,则这个

class文件或者java源代码文件都要放在和package语句中包名对应的目录结构之中。

1,什么都别说,先跟着我来做一把

我们先找一个目录,比如C:\myjob

然后我们建立两个目录,一个叫做src,一个叫做bin

C:\myjob>md src

C:\myjob>md bin

C:\myjob>dir

驱动器 C 中的卷是 LIGHTNING

卷的序列号是 3DD1-83D9

C:\myjob 的目录

2005-12-25  14:33    <DIR>          .

2005-12-25  14:33    <DIR>          ..

2005-12-25  14:34    <DIR>          src

2005-12-25  14:34    <DIR>          bin

               0 个文件              0 字节

               4 个目录    305,123,328 可用字节

C:\myjob>

然后我们在src目录中去写程序

C:\myjob>cd src

C:\myjob\src>

我们写这么4个java文件

////A.java

package com.lightning;

public class A{

{System.out.println("com.lightning.A");}

}

////B.java

package com.lightning;

public class B{

{System.out.println("com.lightning.B");}

}

////C.java

package com;

public class C{

{System.out.println("com.C");}

}

////Test.java

package net.test;

import com.lightning.*;

import com.*;

public class Test{

public static void main(String[] args)

{

        new A();new B();new C();

        System.out.println("net.test.Test");

}

}

写好之后就是这样

C:\myjob\src>dir

驱动器 C 中的卷是 LIGHTNING

卷的序列号是 3DD1-83D9

C:\myjob\src 的目录

2005-12-25  14:34    <DIR>          .

2005-12-25  14:34    <DIR>          ..

2005-12-25  14:39                86 A.java

2005-12-25  14:40                86 B.java

2005-12-25  14:42               194 Test.java

2005-12-25  14:43                68 C.java

               4 个文件           
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java