现在的位置: 首页 > 综合 > 正文

Java-package and import for first perspective

2013年09月03日 ⁄ 综合 ⁄ 共 3437字 ⁄ 字号 评论关闭

包:程序库单元,即当使用关键字import来导入整个程序库(library)时那些变为可用的单元。如:import java.util.*;

这将把标准Java发布的整个实用程序(utility)库都引入到程序中来。例如,java.util中有一个ArrayList类,你现在既可以用全称java.util.ArrayList来指定(这样就不必使用import语句了),也可以仅指定为ArrayList(缘于import)

又如:import java.util.ArrayList;

 

如果想在自己的程序里使用预先定义好的类,那么编译器就必须知道怎么定位它们。

1.如果这个类位于发出调用的那个源文件中,则直接使用这个类。即使这个类在文件的后面才被定义(Java消除了“向前引用”问题:Java要求先编译后运行)

2.如果这个类位于其他文件中,使用import来准确地告诉编译器你想要的类是什么。import指示编译器导入一个包,也就是一个类库(在其他语言中,一个库不仅包含类,还可能包括方法和数据;但是Java中所有的代码都必须写在类里)

 

我们之所以要导入,就是要提供一个管理名字空间的机制。所有类成员的名称都是彼此隔离的,A类中的方法f()B类中的具有相同特征标记(参数列表)的方法f()不会彼此冲突。但是如果类名称相互冲突又该怎么办呢?

这种类名字之间的潜在冲突,要求我们必须使用包对名字空间进行控制。

名字管理十分重要。为了给一个类库生成不会与其他名字混淆的名字,Java采用了与Internet域名相似的指定符。Java设计者希望程序员反转自己的Internet域名,以保证类库名字独一无二。

整个包名(类库名)的字母都要求小写。

 

当编写一个Java源代码文件时,此文件通常被称为编译单元。每个编译单元都必须有一个后缀名.java,而在编译单元内则可以有一个public类,该类的名称必须与文件的名称相同(包括大小写)。每个编译单元只能有一个public类,否则编译器不会接受。如果在该编译单元之中还有额外的类,那么包之外的世界是无法看见这些类的,这是因为它们不是public类,而且它们主要用来为public类提供支持。

当编译一个.java文件时,在.java文件中的每个类都会有一个输出文件,而该输出文件的名称与.java文件中每个类的名称相同,只是多了一个后缀名.class。因此,在编译少量.java文件之后,会得到大量的.class文件。

Java可运行程序是一组可以打包并压缩为Java文档文件(JAR, 使用Javajar文档生成器).class文件。Java解释器负责这些文件的查找、装载和解释(Java中并不强求必须使用解释器。因为存在可以生成单一可执行文件的本地代码Java编译器)

 

程序库实际上是一组类文件。其中每个文件都有一个public(并非强制的,但这很典型),因此每个文件都有一个构件。如果希望这些构件(每一个都有它们自己的独立的.java.class文件)从属于同一个群组,就可以使用关键字package

在文件起始处写:package mypackage

表示你申明该编译单元是名为mypackage的程序库的一部分(package语句必须是文件中除注释以外的第一句程序代码)。换言之,你正在申明该编译单元中的public类名称位于mypackage名称的保护伞下。任何想要使用该名称的人都必须指定全名ormypackage结合使用关键字import

注:Java包的命名规则全部使用小写字母,包括中间的字母也是如此。

牢记:packageimport关键字允许你做的,是将单一的全局名字空间分隔开,使得无论多少人使用Internet以及Java编写类,都不会出现名称冲突问题。

 

Java包从未真正被打包压缩成单一的文件,而且Java包可以由许多.class文件构成。为了解决Java包内文件类型的混乱,可以利用操作系统的层次化的文件结构来解决这一问题,即将特定包的所有.class文件都置于一个目录下。eg:黑白棋系统根目录下有两个文件夹binsrc,在src/edn/hust/hjp中放置.java源文件;在bin/edn/hust/hjp中放置.class文件。

这种层次化的文件结构还可以解决另两个问题:怎样创建独一无二的名称以及怎样查找有可能隐藏于目录结构中某处的类。层次化的文件结构是通过将.class文件所在的路径位置转换成package的名称来实现的。按照惯例,package名称的第一部分是反顺序的类的创建者的Internet域名,Internet域名是独一无二的,因此你的package名称也将是独一无二的,也就不会出现名称冲突的问题了。

层次化的文件结构要求你把package名称分解为你机器上的一个目录。所以当Java需要加载.class文件的时候,它就可以确定.class文件在目录上所处的位置。

ps:当需要为特定的类生成对象or首次访问类的static成员时,程序会自动进行加载。

Java解释器的运行过程如下:第一找出环境变量CLASSPATH(当提及环境变量时,将用大写字母CLASSPATH)CLASSPATH包含一个或多个目录,用作查找.class文件的根目录。从根目录开始,解释器获取包的名称并将每个句点替换成反斜杠,以从CLASSPATH根中产生一个路径名称(于是,package foo.bar.baz就变成为foo/bar/bazfoo/bar/baz或其它,这一切取决于操作系统)。得到的路径会与CLASSPATH中的各个不同的项相连接,解释器就在这些目录中查找与你所要创建的类名称相关的.class文件。举例:

package edu.foresthe.simple; //这个包名称可以用作某些文件的名字空间的保护伞

public class Vector {

       public Vector {

       System.out.println(“edu.foresthe.simple”);

}

}

这个文件被置于我的系统的子目录下:

C:/DOC/JavaT/edu/foresthe/simple

如果沿此路径往回看,可以看到包的名称edu.foresthe.simple,但此路径的第一部分怎么办呢?它将由环境变量CLASSPATH关照,在我的机器上是:

CLASSPATH=.;D:/JAVA/LIB; C:/DOC/JavaT

可以看到,CLASSPATH可以包含多个可供选择的查询路径。

但在使用JAR文件时会有一点变化。必须在类路径中将JAR文件的名称写清楚,而不仅是指明它所在位置的目录。因此,对于一个名为grape.jarJAR文件,类路径应包括:

CLASSPATH=.;D:/JAVA/LIB;C:/flavors/grape.jar

当编译器碰到import语句导入simple库时,就开始在CLASSPATH所指定的目录中查找,在C:/DOC/JavaT中找到edu/foresthe/simple目录,然后从已编译的文件中找出名称相符者(Vector而言是Vector.class)。注意:Vector类以及要使用的方法必须都是public的。

 

冲突

如果将两个含有相同名称的程序库以”*”形式同时导入,将会出现什么情况呢?例如:

import edu.foresthe.simple.*;

import java.util.*;

由于java.util.*也含有一个Vector类,这就存在潜在的冲突。但是只要你不写那些导致冲突的程序代码,就不会有什么问题。如果要创建一个Vector类,就会产生冲突。

Vector v = new Vector();

这行到底取用哪个Vector类?编译器不知道,读者也不知道。于是编译器提出错误信息,强制你明确指明。例如:

java.util.Vector v = new java.util.Vector();

 

对使用包的忠告

务必记住,无论何时创建包,都已经在给定包的名称的时候隐含地指定了目录结构。这个包必须位于其名称所指定的目录之中,而该目录必须是在以CLASSPATH开始的目录中可以查询到的。

使用关键字package,必须遵守“包的名称对应目录路径”的规则,否则会被告知无法找到特定的类。如果你收到类似信息,就注释掉package语句试一下,这样容易找到问题出在哪里。

抱歉!评论已关闭.