一些人用了一阵子的Java,可是对于 Java 的 package 跟 import 还是不太了解。很多人以为原始码 .java 文件中的 import 会让编译器把所 import 的程序通通写到编译好的 .class 档案中,或是认为 import 跟 C/C++ 的 #include 相似,实际上,这是错误的观念。

让我们先了解一下,Java 的 package 到底有何用处。

其实,package 名称就像是我们的姓,而 class 名称就像是我们的名字。package 名称有很多 . 的,就好像是复姓。比如说 java.lang.String,就是复姓 java.lang,名字为 String 的类别;java.io.InputStream 则是复姓java.io,名字为 InputStream 的类别。

Java 会使用 package 这种机制的原因也非常明显,就像我们取姓名一样,光是一间学校的同一届同学中,就有可能会出现不少同名的同学,如果不取姓的话,那学校在处理学生数据,或是同学彼此之间的称呼,就会发生很大的困扰。相同的,全世界的 Java 类别数量,恐怕比台湾人口还多,而且还不断的在成长当中,如果类别不使用套件名称,那在用到相同名称的不同类别时,就会产生极大的困扰。幸运的是,Java 的套件名称我们可以自己取,不像人的姓没有太大的选择 ( 所以有很多同名同姓的 ),如果依照 Sun 的规范来取套件名称,那理论上不同人所取的套件名称不会相同 ( 请参阅 "命名惯例"的相关文章 ),也就不会发生名称冲突的情况。

可是问题来了,因为很多套件的名称非常的长,在写程序时,会多打好多字,花费不少时间,比如说在A.B.C文件下有Point和Circle两个类,现在在程序中要调用:

     A.B.C.Point  P1=new A.B.C.Point();A.B.C.Circle  C1=new A.B.C.Circle();

实在是不美观又麻烦.于是,Sun 想了一个办法,就是 import. 就是在程序一开头的时候,说明程序中会用到那些类的路径.首先,在档案开头写:

     import A.B.C.Point;import A.B.C.Circle;

这两行说明了类的路径,所以当程序中提到Point就是指A.B.C.Point,而Circle就是指A.B.C.Circle,依此类推。于是原来的程序就变成:

     Point  P1=new Point();Circle  C1=new Circle();  

这样看起来是不是清爽多了呢?如果这些类别用的次数很多,那就更能体会到import 的好处了。可是这样还是不够,因为懒是人的天性,还是会有人觉得打太多 import 了也很浪费时间,于是 Sun 又提供了一个方法:

    import A.B.C.*; /*意思就是,等一下程序中提到的没有姓名的类别,全都包含在A.B.C这个目录中。*/

注意点:但我们在程序中经常使用System.out这个类,为什么没有import System.out呢,因为java.lang 这个套件实在是太常太常太常用到了,几乎没有程序不用它的,所以不管你有没有写 import java.lang;,编译器都会自动帮你补上,也就是说编译器只要看到没有姓的类别,它就会自动去 java.lang 里面找找看,看这个类别是不是属于这个套件的。所以我们就不用特别去import java.lang 了。

为甚么我一开始说 import 跟 #include 不同呢?因为 import 的功能到此为止,它不像 #include 一样,会将档案内容载入进来。import 只是请编译器帮你打字,让编译器把没有姓的类别加上姓,并不会把别的文件的程式码写进来。如果你想练习打字,可以不要使用 import,只要在用到类别的时候,用它的全部姓名来称呼它就行了(就像例子一开始那样),跟使用 import 完全没有甚么两样。

先介绍Java的Package机制

基本原则:需要将类文件切实安置到其所归属之Package所对应的相对路径下。

例如:以下面程序为例:假设此Hello.java文件在D:Java下

package  A;
public class Hello{public static void main(String args[]){   System.out.println("Hello World!");}
}D:\Java>javac  Hello.java  此程序可以编译通过.接着执行。
D:\Java>java  Hello       但是执行时,却提示以下错误!
Exception in thread "main" java.lang.NoClassDefFoundError: hello (wrong name: A/Hello)at java.lang.ClassLoader.defineClass0(Native Method)at java.lang.ClassLoader.defineClass(ClassLoader.java:537)at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:123)at java.net.URLClassLoader.defineClass(URLClassLoader.java:251)at java.net.URLClassLoader.access$100(URLClassLoader.java:55)at java.net.URLClassLoader$1.run(URLClassLoader.java:194)at java.security.AccessController.doPrivileged(Native Method)at java.net.URLClassLoader.findClass(URLClassLoader.java:187)at java.lang.ClassLoader.loadClass(ClassLoader.java:289)at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:274)at java.lang.ClassLoader.loadClass(ClassLoader.java:235)at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:302)

原因是我们把生成的Hello.class规定打包在D:JavaA文件中,必须在A文件中才能去运行。所以应该在D:Java目录下建立一个A目录,然后把把Hello.class放在它下面,执行时,可正常通过!
D:Java>java A.hello 就会输出:Hello world!

现在介绍Java的import机制

我们在D:Java目录下建立一个JInTian.java文件,其内容如下:

import  A.Hello;
public class JInTian{public static void main(String[] args){Hello  Hello1=new Hello();}
}D:\Java\>javac JInTian.java   编译成功!D:\Java\>java  JInTian      运行成功!

也就是你在JInTian.class中成功的引用了Hello.class这个类,是通过import A.Hello来实现的,如果你没有这句话,就会提示不能找到Hello这个类。

提示1:如果你在D:Java目录下仍保留一个Hello.java文件的话,执行对主程序的编译命令时仍会报错!你自己可以试试呀!
提示2:如果你删除D:JavaAHello.java文件的话,只留Hello.class文件,执行对主程序的编译命令时是可以通过,此时可以不需要子程序的源代码。
提出一个问题:如果把目录A剪切到其它目录,如D盘根目录下,在A目录如果执行编译和执行命令呢?
很明显,会报以下错误!当然了,前提条件是你没有设置classpath路径,其实只要没把类搜索路径设置到我这个位置就会出错的!你试试吧!

由于大家对package的使用存在太多困惑,我在这里将自己对于package的使用的领悟进行一点总结:

  package中所存放的文件

  所有文件,不过一般分一下就分这三种

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

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

  3,其他文件,其他任何文件,也称为resource

  例如图片文件,xml文件,mp3文件,avi文件,文本文件……

  package是什么

  package好比java用来组织文件的一种虚拟文件系统。package把源代码.java文件,.class文件和其他文件有条理的进行一个组织,以供java来使用。package是将文件组织在一颗类似unix,linux文件系统的树结构里面,它有一个根"/",然后从根开始有目录和文件,目录中也还有文件和目录。

  package怎么实现的呢?

  源代码的要求最严格,而一旦源代码自己声明了在哪个package路径之下,class也就有了自己在哪个package下面的信息,就是那句程序开头的"package xx.xx.xx"。有人问,为什么要有这个信息,直接放目录结构里不就好了么?是啊,直接放目录中确实可以找到.class和.java,但是如果我要输出这个.class是属于哪个package的,该怎么办?所以我们需要在.class里面留一个package的信息。如果我们要区分同样名称为A.class的类怎么办?所以我们需要在.class里面留一个package的信息。

  .java文件是一个独立的编译单元,类似c++里面的cpp文件,但是它不需要.h文件,只要.java就足够了,一个.java文件里面可以包含一个public的类,若干package类(package类特征是没有任何访问控制修饰),还有内隐类的话,则还可以包含若干protected和private的类。每个类,都会在编译的时候生成一个独立的.class文件,所以.java和.class不是一对一,而是一对多的关系,不过.java和public的类是一对一的。所有这些.class,都由这个.java开头的package语句来确定自己在package中的位置。

  package xx.bb.aa;

  说明这个.java编译单元中的所有类都放到xx.bb.aa这个package里面。而对应的,必须把这个.java文件放在xx目录下bb目录下的aa目录里面。如果一个.java文件没有任何package语句,那么这个.java里面的所有类都在package的"/"下面,也称之为default package。可以看出你一般从任何java教科书上写的第一个hello world程序的那个类是在defaultpackage里面的。有了package语句,情况就复杂一点了。这个编译单元.java必须放在package名对应的目录之下。而生成的class文件也要放在对应的目录结构之下才能正常运作。

  例如:

    /* A.java */ package aaa.bbb.ccc; public class A{ B b=new B(); } /* B.java*/ package aaa.bbb.ccc; public class B{}

  编译时候怎么填参数呢?我根据package+文件名的格式来写,

  javac aaa.bbb.ccc.A.java

  漂亮吧?可惜不工作。非要使用合法的路径名才行:

  javac aaa/bbb/ccc/A.java

  但是你发现生成的class丢失了目录结构,直接出现在当前目录下……

  最好的方式是

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

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

  package与classpath不得不说的事

  对于java来讲,所有需要的程序和资源都要以package的形式来组织和读取。

  那么classpath又是什么呢?

  所有放到设定到classpath里面的东西就是package所包纳的资源。classpath的写法如同path,只是里面可以写的一般只有zip文件、jar文件和目录。多个元素之间用当前系统路径分隔符间隔开了,linux上分隔符号是":",windows上是";"。classpath在java里面是被一个叫做classloader的东西所使用的,classloader顾名思义,就是load class用的,但它也可以load其它在package里面的东西。现在的java里面classloader是有阶层关系的,一般我们所常接触到的CLASSPATH环境变量,javac,java的-cp,-classpath参数所给的classpath信息是被appclassloader所使用的。而appclassloader其实是第三层的classloader,最高层的classloader叫做bootstrap classloader,它不是java写的classloader,而是c++写成的,第二层叫做extclassloader,默认包纳是jre/lib/ext里面的classes目录和所有jar文件作为内容。第三层才是我们命令行参数,或者不用命令行参数,用系统环境变量指定classpath的使用者app classloader,这是最基本的java se。如果是java ee,有了服务器,容器,还有更多层的classloader,他们在app classloader的更下面,例如tomcat的某web应用程序的web-inf/lib中的jar,zip和classes目录,是app之下好几层的classloader使用的。

  你可以建立自己的classloader,都在app classloader之下,实际上tomcat本身也是这样建立classloader的。分层的目的是为了安全,试想你加入搞了一个classloader,从网络上读取class,而在里面写上格式化硬盘的代码,人家一读运行,那不就挂了,所以分层之后,首先从最高层读,没有再往下找,找到就不着了。一般java所必须的rt.jar里面的若干class,是在bootstrap classloader启动的时候读入的,而jmf使用的几个jar,是在ext classloader里面读入的。也就是说,读入这些class的时候,我们的appclassloader还在娘胎里呢,所以你在CLASS PATH中指定rt.jar是完全愚蠢多余的。java绝对不会到这里找rt.jar,而bootstrapclassloader如果你不特别要修改,它是常量,不需要你care。

  import干吗用的?

  import只是一种让你偷点懒少打字的方法,绝对不会影响你的classpath,这点你要好好记住,没有非用import不可的理由,用了import也不会起到类似c里面嵌入某文件内容的效果,它只是一种省事的办法。不在classpath中的class,任你再import也无济于事。

  如果你不用import,你用ArrayList这个类,就需要写

  java.util.ArrayList。

  而用了import java.util.ArrayList;的话

  以后代码中写ArrayList就可以了,省事。import可以使用通配符代表某package下所有的class,不包括子目录。

  import java.awt.*

  不等于

  import java.awt.*import java.awt.event.*

  如果你要简写java.awt.event下和java.awt下的类,你不能偷懒,两个都要import。

【转】Java的package和import机制相关推荐

  1. 关于java语言中的package和import机制

    目录 一.为什么要使用package 二.package怎么用 三.在cmd中对于带有package的java程序怎么编译?怎么运行? 四.关于import的使用: 1.impo什么时候使用? 2.i ...

  2. Java package 与 import

    有些人写了一阵子 Java,可是对于 Java 的 package 跟 import 还是不太了解.很多人以为原始码 .java 文件中的 import 会让编译器把所 import 的程序通通写到编 ...

  3. java垃圾回收机制_乐字节Java|GC垃圾回收机制、package和import语句

    本文接上一篇:乐字节Java|this关键字.static关键字.block块.本文是接着讲述JavaGC垃圾回收机制.package 和 import语句. 一.GC垃圾回收机制 GC全名:Garb ...

  4. JAVA - package与import解析(一)

    一.为什么要引入package和import? 这个问题和c++中引入命名空间是一样的,也是为了解决重名问题.java通过包机制来解决重名问题,也就相当于给重名的代码加一系列前缀,从而达到唯一标识的作 ...

  5. JAVA入门级教学之(package和import)

    目录 JAVA入门级教学之(package和import) 1.包又称为package 2.怎么定义package? 3.包名的命名规范: 4.包名要求全部小写,包名也是标识符,必须遵守标识符的命名规 ...

  6. java中import机制(指定import和import *的区别)

    java中有两种包的导入机制,总结如下: 单类型导入(single-type-import),              例如 import java.io.File; 按需类型导入(type-imp ...

  7. Java - package和import

    package 包的 3 个作用如下: 1.区分相同名称的类. 2.能够较好地管理大量的类. 3.控制访问范围. Java 包的命名规则如下: 1.包名全部由小写字母(多个单词也全部小写). 2.如果 ...

  8. java基础之package和import语句

    文章目录 前言 一.包(package) 二.import关键字 三 java解释器 注意: 总结 前言 在同一个类中,方法名重复可以利用方法重载,数据成员与参数名重复可以利用this关键字,那么在一 ...

  9. Java基础-package包机制

    关于java语言当中的包机制: 1.包又称为package,java中引入package这种语法机制主要是为了方便程序的管理.不同功能的类被分门别类放到不同的软件包当中,查找比较方便,管理比较方便,易 ...

  10. java 同一个package import_【编程基础】Java 中的Package和Import

    开始要逐步去熟悉最基础的语法了,幸好之前是有底子的,所以理解也不难,  import Package 有点类似C语言中的#include [头文件] 为什么要用包(Package) 当一个大型程序交由 ...

最新文章

  1. 鱼佬:从数据竞赛到工作!
  2. AS整理代码快捷键 ctl+alt+L
  3. 服务器磁盘空间已满但并没有什么文件,win10 D盘没多少文件,但磁盘却满了
  4. c++:opencv的安装和配置
  5. python内核死亡的原因_Python的内核由于DLL而死亡
  6. 学习《Building Applications with FME Objects》 之四 从数据集读取要素
  7. 【数据结构与算法】浅谈队列的应用
  8. (王道408考研操作系统)第二章进程管理-第一节4:进程通信(配合Linux)
  9. 华为Mate 40 Pro首碎照来了,网友酸了:不要给我
  10. vue-admin自定义后台管理系统(二)之vue-cli3创建前端项目
  11. 西安后宰门小学_【云端论坛】走向未来的墙中老校 ——后宰门小学“名校+”教育集团云论坛精彩绽放...
  12. chapter 9 series
  13. 机器视觉的四大类应用
  14. Oracle Spatial详解
  15. 如何使用视频压缩软件,压缩视频大小 ?
  16. office2019 retail零售版转换vol批量授权版 cmd批处理命令 kms示例
  17. Druid简介及常用查询操作
  18. 【淘宝】图片放大 代码
  19. 【Java位运算】使用快速幂方法求指数的值
  20. sqlserver 之STUFF的运用

热门文章

  1. MDK 中 [WEAK] 的作用
  2. [No0000DD]C# StringEx 扩展字符串类 类封装
  3. MongoDB集群架构 调整,增加延迟备份节点服务器,删除仲裁节点(9)
  4. Android ListView上拉获取下一页
  5. 根据输入时间判断年龄是否在18~68周岁之间
  6. 什么样的终端才是最合适桌面虚拟化的呢?
  7. file owner
  8. jdk8,lambda表达(简化代码)
  9. HZNU 2019 Summer training 7
  10. linux 搭建svn注意事项