Java 面向对象 - Java 包(package)

2022年8月2日
大约 7 分钟

Java 面向对象 - Java 包(package)

什么是Java包?

包是Java语言提供的一种区别类名字命名空间的机制,它是类的一种文件组织和管理方式、是一组功能相似或相关的类或接口的集合。Java package提供了访问权限和命名的管理机制,它是Java中很基础却又非常重要的一个概念。

包的作用

1)对类文件进行分类管理;

2)给类提供命名空间,相当于一张封装形式(类似C++中namespace);

3)类名的全称是:包名.类名,即“姓”+“名”;

4)包定义放在文件开头,导入包和类也是一样;

5)把功能相似或相关的类或接口组织在同一个包中,方便类的查找和使用;

6)如同文件夹一样,包也采用了树形目录的存储方式。同一个包中的类名字是不同的,不同的包中的类的名字是可以相同的,当同时调用两个不同包中相同类名的类时,应该加上包名加以区别。因此,包可以避免名字冲突;

7)包也限定了访问权限,拥有包访问权限的类才能访问某个包中的类。

包的命名规则

  1. 全小写;
  2. 使用域名反转的方式定义,例如素文宅yoodb.com的项目,定义包名称为com.yoodb;
  3. 如果细分还可以引入功能定义部分,例如数据库访问com.yoodb.dao;

import关键字

import pack.ClassA; //导入包pack的classA类
import pack.*;      //导入包pack下的所有类,这个方便调用导入一个包下多个类的写法

当导入包类以后,可以通过类实例化对象,再通过对象调用类中具体实现方法了。

演示代码一

实例:

import java.util.Scanner;

Scanner scan = new Scanner(System.in); //实例化类Scanner
String str   = scan.nextline();//调用Scanner中方法nexline(),从输入流中获取一行字符串

演示代码二

如果导入两个包后,都存在相同的类,则在使用类的时候指明哪个包。

import pack1.ClassA;
import pack2.ClassA;
pack2.ClassA cla = new pack2.ClassA(); //指明调用的是哪个包的方法

演示代码三

包的建立非常简单,在Java程序加入package。我们以LineData类为例,将它放入包中:

package com.yoodb.blog;
public class LineData {
    /**
    * constructor
    */
    public LineData(int h) {
        this.height = h;
        System.out.println("I'm born");
    }
    /**
    * accessor
    */
    public int getHeight() {
        return this.height;
    }
    /**
    * mutator
    */
    public void growHeight(int h) {
        this.height = this.height + h;
    }
    private int height;
}

上面的第一行语句,代码如下:

package com.yoodb.blog;

表示该程序在com.yoodb.blog包中。com.yoodb(yoodb.com的反写)表示包作者的域名(个人博客网站:blog.yoodb.com)。Java要求包要有域名前缀,以便区分不同作者。article为进一步的本地路径名。com.yoodb.blog共同构成了包的名字。

包为Java程序提供了一个命名空间(name space)。一个Java类的完整路径由它的包和类名共同构成,比如com.yoodb.blog.LineData。相应的LineData.java程序要放在com/yoodb/blog/下。类是由完整的路径识别的,所以不同的包中可以有同名的类,Java不会混淆。比如com.yoodb.blog.LineData和com.yoodb.article.LineData是表示两个不同的类。

再看一个细节。LineData类是public的,其构造方法也是public的,所以任意其他对象都可以调用该类。我们之前说过,一个Java文件中只能有一个public的类,该类要去.java文件同名。一个类可以没有public关键字,它实际上也表示一种权限: 该类在它所在的包中可见。也就是说,包中的其他Java程序可以访问该类。这是Java中的默认访问权限。

同样,对象的成员也可以是默认权限(包中可见)。比如我们去掉getHeight()方法前面的public关键字。

包的调用

我们只需要将LineData.java编译的LineData.class放入相应的文件夹就可以了。比如,我将LineData.class放入com/yoodb/blog/中。实际上,你也可以把.java文件放入相应路径,Java会在使用时自动编译。

如果整个包()也就是com文件夹)位于当前的工作路径中,那么不需要特别的设置,就可以使用包了,比如下面的TestAgain.java:

代码如下:

import com.yoodb.blog.*;
public class TestAgain {
    public static void main(String[] args) {
        LineData aPerson = new LineData(180);
        System.out.println(aPerson.getHeight());
    }
}

import用于识别路径。利用import语句,我们可以引入相应路径下的类。*表示引入blog文件夹下的所有类。在TestAgain中,我们直接使用了LineData类。

我们也可以提供类的完整的路径。这可以区分同名但不同路径的类,比如:

代码如下:

public class TestAgain {
    public static void main(String[] args) {
        com.yoodb.blog.LineData aPerson = new com.yoodb.blog.LineData(180);
        System.out.println(aPerson.getHeight());
    }
}

由于我们提供了完整的类路径,所以不需要使用import语句。

如果包没有放在当前工作路径下,我们在使用包时,需要通知Java。比如,我们将包放在/home/yoodb/javapackage中,这样LineData.class位于(Linux系统目录格式)/home/yoodb/javapackage/com/yoodb/blog/LineData.class,而我们的工作路径为/home/yoodb。这样,包就无法被找到。一个方法是在使用javac和java时,用-classpath说明包所在的文件夹路径,比如:

代码如下:

$javac -classpath /home/yoodb/javapackage:. TestAgain.java
$java -classpath /home/yoodb/javapackage:. TestAgain

就是从/home/yoodb/javapackage和工作路径(.)中寻找包。Java可以从/home/yoodb/javapackage中可以找到LineData类,从.中可以找到TestAgain类。

另外也可以设置系统的CLASSPATH环境变量,将上述路径加入到该变量中,而不用每次都键入-classpath选项。

类似于包的机制在其他语言中也很常见,比如Python中的import机制。它们都是为了更好的组织和使用已有的程序。利用包,我们可以比较容易的拓展Java程序,使用已有的Java程序库。注意到,包管理的是.class文件。Java号称"一次编译,处处运行" (Compile Once, run anywhere)。.class文件可以在任意装有Java虚拟机(JVM, Java Virtual Machine)的平台上运行,这帮助我们克服了系统差异造成的程序移植困难。

系统之间的差异可以非常大。如果我们用C语言编写程序,需要将源程序在各个平台上重新编译,以适应不同的硬件条件。 Java虚拟机衔接了平台和Java宇宙,它构成了硬件和编程逻辑的中间层。JVM隐藏了硬件差异,提供给程序员一个“标准”的Java宇宙。而.class文件可以看做这个 Java宇宙中流通的通货。在JVM的基础设施下,加上包的管理辅助,Java程序实现了良好的可移植性(portability)。

JDK自带系统常包

Java.lang包:java的核心类库,包含了运行java程序必不可少的系统类,如基本数据类型、基本数学函数、字符串处理、线程、异常处理类等,系统缺省加载这个包

java.io包:java语言的标准输入/输出类库,如基本输入/输出流、文件输入/输出、过滤输入/输出流等等

java.util包:Java的实用工具类库(java.utilData)类、日历(Calendar)类来产生和获取日期及时间,提供随机数(Random)类产生各种类型的随机数,还提供了堆栈(Stack)、向量(Vector) 、位集合(Bitset)以及哈希表(Hashtable)等类来表示相应的数据结构。包含如处理时间的date类,处理变成数组的Vector类,以及stack和HashTable类

java.util.zip包:实现文件压缩功能

java.lang.reflect包:提供用于反射对象的工具

java.awt.image包:处理和操纵来自于网上的图片的java工具类库

java.wat.peer包:很少在程序中直接用到,使得同一个java程序在不同的软硬件平台上运行

java.applet包

java.NET包:实现网络功能的类库有Socket类、ServerSocket类

java.corba包和java.corba.orb包

java.awt.datatransfer包:处理数据传输的工具类,包括剪贴板,字符串发送器等

java.awt包:构建图形用户界面(GUI)的类库,低级绘图操作Graphics类,图形界面组件和布局管理如 Checkbox类、Container类、LayoutManger接口等,以及界面用户交互控制和事件响应,如Event类

java.awt.event包:GUI事件处理包

java.sql包:实现JDBC的类库等