首页 > 编程笔记 > Java笔记 阅读:37

Java package包的定义和使用(非常详细)

操作系统中有目录和文件的概念,其实在 Java 中,包和类的关系有点像目录和文件的关系,包就像是目录而类则像是文件。

一个 Java 项目中的包和类,展开后就是一个文件目录结构,如下图所示。


图 1 包与类

其中,com 是包(目录),backend 和 frontend 都是子包(子目录),frontend 包下有三个 Java 类(文件),而 backend 包下还有 core 和 util 两个子包,这两个子包下也分别有三个 Java 类。

为什么需要包

首先,假设不存在“包”的概念,那么会存在类名冲突的问题。所谓类名冲突,就是在使用时无法区分相同名称的类。

如下图所示,JDK 内置了一个 String 类,我们自己再定义一个 String 类,那么当我们要使用这两个 String 类时会无法区分它们。


图 2 相同名称的类

其次,“包”机制能让项目结构更加清晰,从而方便维护。实际的 Java 项目中一般会包含大量类,小项目中可能有几十至上百个类,而大中型项目中往往有成百上千个类,如果将所有类都放到一起会是难以想象的。而通过包则可以按照逻辑划分将不同模块的 Java 类放到不同的包中,这样能使项目结构更加清晰,同时使开发维护工作也更方便。

最后,“包”机制还提供了访问控制功能,在 Java 中可以通过访问修饰符(如 protected、public 等)来控制类的访问范围,这个范围与包相关。

Java包的定义

要对一个类进行包定义非常简单,只需在类源文件(.java)的第一行添加包定义语句,具体的语法格式如下:
package 包名;
除了类,接口和枚举的包声明的格式也是一样的。

下面来看包定义的一个示例:
package com.seaboat;

public class Student {
    int id;
    int age;
    String name;

    public Student(int id, int age, String name) {
        this.id = id;
        this.age = age;
        this.name = name;
    }

    public static void main(String[] args) {
        Student xiaoming = new Student(1, 10, "小明");
        System.out.println(xiaoming.name + "," + xiaoming.age);
    }
}
可以看到,我们只需在第一行添加“package com.seaboat;”就能将 Student 类定义为 com.seaboat 包,该包包含了两个层次,com 是第一层,seaboat 是第二层,seaboat 是 com 的子包。

实际上包的层次数可以是任意的,包的层次间用“.”点号进行分隔,同时需要注意包名必须全部为小写。

Java包的导入

在实际开发过程中,会将不同的 Java 类按照功能模块或者业务逻辑进行划分,将属于某个模块的所有类统一放到一个包内。假如要在某个包的类中使用另一个包中的类,就需要先导入这个包,然后才能使用该包中的类。

下面看看导入包和类的语法,通过 import 关键字来完成导入,格式是:
import 包.类;
import 包.*;
前者导入的是某个包中的具体某个类,而后者则是导入某个包中的所有类。

下面看一个示例:
package com.seaboat.test;

import com.seaboat.Student;

public class Teacher {
    public String name;
    public Student student;
}
com.seaboat 包下有一个 Student 类,如下图所示:


图 3 包目录1

如果 com.seaboat.test 包下的 Teacher 类要使用 Student 类则需要先将其导入,导入命令为“import com.seaboat. Student;”。假如不导入直接使用则会引发编译错误,具体错误消息为“Student cannot be resolved to a type”。

类似地,可以使用“import com.seaboat.*;”来实现类导入,这种星号实际上是一种通配符,所以需要在编译时进行类搜索工作,从而增加编译的时间。

如果要导入多个包和类,可以通过多行 import 语句来实现。例如下面的程序中,为了导入下图的 Student 类和 Grade 类,可以通过两行 import 语句来实现。


图 4 包目录2
package com.seaboat.test;

import com.seaboat.Student;
import com.seaboat.Grade;

public class Teacher {
    public String name;
    public Student student;
    public Grade grade;
}
此外,如果我们不想使用 import 语句来导入包和类,可以通过全限定名的方式来使用某个类,即在使用类时以“包.类”的格式来声明。通过下面的程序大家就能明白如何使用全限定名的方式了。
public class Teacher2 {
    public String name;
    public com.seaboat.Student xiaoming = new com.seaboat.Student(1, 10, "小明");
}
使用全限定名方式还能解决同名类的问题,比如我们在 com.seaboat.util 包下创建了一个 String 类,这个类与 Java 语言提供的 String 类同名,当我们要同时使用它们时可以通过全限定名来区分,例如:
public class Test {
    public static void main(java.lang.String[] args) {
        java.lang.String string = new java.lang.String();
        com.seaboat.util.String string2 = new com.seaboat.util.String();
    }
}

Java内置包与自定义包

总体而言,我们可以把 Java 的包分为 Java 语言内置包和自定义包,内置包是 Java 为了方便开发者提供的语言层面的常用包,自定义包则是开发者根据实际需要自行创建的包。

下面简单介绍几个常见的内置包,包括 java.lang、java.io、java.net 以及 java.util:

相关文章