25. 【Java教程】Java 包

简介: 25. 【Java教程】Java 包

当我们的程序规模越来越大,类的数量也会随之增多,数量繁多的类会造成项目的混乱,不易于维护管理。本小节所介绍的包就是为了将类分类而产生的,我们可以使用包让程序结构更加清晰且易于管理。本小节将会学习到什么是包如何声明包包作用域以及包的命名规范等知识点。

1. 概述

1.1 什么是包

包是一个命名空间,它可以将类和接口进行分组。

从概念上讲,我们可以将包看作是计算机上的不同文件夹。例如,我们可以将图片保存在一个文件夹中,将视频保存在另一个文件夹中。

1.2 为什么需要包

正如我们在前言中所提到的,当程序规模越来越大,类的数量也会随之增多。使用包将这些类分组后,可以让类更易于查找和使用,也可以避免命名冲突,还可以控制访问。


易于查找和使用很容易理解,试想我们电脑的某一个文件夹中,存放着成百上千的各类文件,即使使用搜索功能都不能迅速定位到我们想要的文件,而将这些文件按照功能或特点分类存入到不同的文件夹下,就可以大大提高我们查找和使用的效率。对于 Java 语言的类也是同样的道理。


对于命名冲突,我们来看实际开发中的一个例子:一个 Java 工程由 3 个程序员协同开发,程序员 A 写了一个工具类 Util,程序员 B 也写了一个工具类 Util,程序员 C 既想使用 A 的 Util,又想使用 B 的 Util,这个时候可以分别将 A、B 两个人的 Util 类放入两个不同的包下,就可以解决命名冲突了。


对于控制访问,我们将在本小节的包作用域部分举例讲解。

2. 包声明

2.1 语法

在一个类中,使用关键字 package 在类的顶部声明一个包:

package service;
 
public class DemoService {
    ...
}

面的代码就表示 DemoService 类放到了 service 包下,我们也可以说:DemoServiceservice 包中声明。我们的类如果在包中声明,那么类就必须放置在源码目录下以包名称命名的子目录中。这样编译器才能在系统中找到 Java 文件。

2.2 实例

下面我们使用 IntelliJ IDEA 来演示一个简单的建包到建类的过程。


新建一个名为 mybj 的工程,之前我们已经学过如何在 IDE 中新建工程,因此这里不再截图演示。查看下图,mybj 是工程名,src 是源码目录。

首先在源码目录新建一个包,命名为 service。在 src 目录上点击鼠标右键 -> New -> Package

填入包名 service

输入 Enter 完成包的新建,此时工程结构如下:

接下来在包下面新建一个 DemoService 类。在 service 点击右键 -> New -> Java Class,输入类名称 DemoService 完成新建,此时工程结构如下:

而 IDE 也会在类的顶部自动为我们声明包:

这样就完成了一个包到类的新建。

重复以上步骤,我们接着在源码目录下新建一个 util 包,在 util 包中新建一个 DemoUtil 类。

此时,mybj 工程在物理硬盘上的文件结构为:

├── mybj
│   └── src
│       ├── service
│       │   └── DemoService.java
│       └── util
│           └── DemoUtil.java

通过上述一系列演示,我们验证了这个结论:所有的 Java 文件对应的目录层级要和包的层级保持一致。


另外,包下面也可以包含子包,子包中也可以声明类,例如,可以在上面的 service 包下新建一个 demo 包,在 demo 包下新建一个 DemoClass 类。如下代码可以看到类顶部包的声明,要使用. 分隔多个包名:


1. 
package service.demo;
2. 
3. public class DemoClass {
4. }

3. 导入包

3.1 完整类名导入

在类名前面加上包名(我们称为完整类名),就可以使用指定包中的类。例如,对与上面示例的项目结构,我们想在 DemoService 类中使用 DemoUtil 类,可以这样写:

package service;
 
public class DemoService {
    util.DemoUtil demoUtil = new util.DemoUtil();
}

如果使用同一包中的类,则不必在类前面指定包名。

3.2 import 关键字导入

上面的语法比较冗长,我们可以使用 import 关键字在文件顶部导入指定包中类,在代码中就不必指定包名来使用类了。例如,上面的代码可以改成写:

package service;
 
import util.DemoUtil;
 
public class DemoService {
    DemoUtil demoUtil = new DemoUtil();
}

Tips:如果有两个或多个类名相同,那么就不能使用 import 关键字同时导入了,此时建议使用完整类名的方式使用类。当然,实际的编码中,我们也不推荐命名多个同名类。



3.3 通配符导入

在使用 import 关键字时,可以使用通配符 * 来导入指定包下面的所有类。例如:

package service;
 
import util.*;
 
public class DemoService {
    DemoUtil demoUtil = new DemoUtil();
}

尽管它看起来非常方便,但是我们不推荐这种写法。一方面降低了代码的可读性,另外也可能导致一些问题。

还有一点需要特别提醒,java.lang 包中的所有类会都被编译器隐式导入,所以在使用诸如 SystemString 等类的时候,我们不需要手动导入。

4. 包作用域

所谓包作用域,就是没有使用访问修饰符修饰的字段和方法。同一个包中的类,可以访问包作用域的字段和方法。

例如,在 com.mybj 包下面有一个 Student 类:

package com.mybj;
 
public class Student {
 
    // 包作用域的属性
    String name;
 
    // 包作用域的方法
    void sayHello() {
        System.out.println("你好!" + name);
    }
 
}

com.mybj 包下面的 Test 类,访问 Student 类中的字段和方法:

package com.mybj;
 
public class Test {
    public static void main(String[] args) {
        Student student = new Student();
        // 操作包作用域下属性
        student.name = "Colorful";
        // 访问包作用域下的方法
        student.sayHello();
    }
}

由于 StudentTest 都属于 com.mybj 包,所以可以访问包作用域内的字段和方法。

5. 包命名规范

包名应该使用全小写字母命名,这样易于将包名与类名区分开。

为了避免名称冲突,通常建议以公司域名的倒置来确保唯一性。例如,码云笔记域名为 mybj123.com,项目的包命就应该为 com.mybj,其具体的子包可根据功能业务命名。


再举几个例子,大名鼎鼎的 Apache 软件基金会的包命名为 org.apache,Java 领域最知名开源框架 Spring 包名为 org.springframework。

6. 小结

本小节我们学习了 Java 包的定义与使用,Java 提供包的机制主要是为了类避免命名冲突。我们也知道了如何声明包、如何导入包以及包作用域的概念,实际项目的包名推荐使用域名倒置。

包的使用,除了在我们自己编写的项目中非常常见,你也可以翻阅 JDK 的源码,Java 平台按照功能将类放入了不同的包中。例如:基础的类在 java.lang 包中,用于读写的类在 java.io 包中,一些工具类放在 java.util 包中。Java 平台由成百上千的类组成,把这些类放入包中,可以使程序结构井井有条。


相关文章
|
3天前
|
Java 测试技术 Python
《手把手教你》系列基础篇(七十七)-java+ selenium自动化测试-框架设计基础-TestNG依赖测试- 上篇(详解教程)
【6月更文挑战第18天】TestNG是一个Java测试框架,它允许在测试方法间定义执行顺序和依赖关系。当不指定依赖时,TestNG默认按方法名首字母排序执行。`@Test`注解的`dependsOnMethods`属性用于指定方法依赖,如`test1`依赖`test4`,则实际执行顺序为`test4`、`test2`、`test3`、`test1`。如果依赖的方法失败,后续依赖的方法将被跳过。此外,`dependsOnGroups`属性通过组名指定依赖,方便管理多个相关测试方法。通过`groups`定义方法所属组,然后在其他方法中用`dependsOnGroups`引用这些组。
19 5
|
2天前
|
Java 开发者 UED
【实战宝典】Java异常处理大师级教程:throws关键字,让异常声明成为你的专属标签!
【6月更文挑战第19天】在Java中,`throws`关键字是异常处理的关键,它提升了方法签名的透明度和代码质量。不使用`throws`时,未捕获的异常可能导致程序崩溃。例如,`readFileContent`方法若不声明`throws IOException`,则隐藏了可能的风险。而明确声明如`throws IOException`,提醒调用者需处理异常,增强代码稳定性。
|
23小时前
|
Java
杨老师课堂_Java教程第五篇之函数运用
杨老师课堂_Java教程第五篇之函数运用
9 1
|
2天前
|
XML Web App开发 测试技术
《手把手教你》系列基础篇(七十八)-java+ selenium自动化测试-框架设计基础-TestNG依赖测试- 中篇(详解教程)
【6月更文挑战第19天】本文介绍了使用TestNG框架配置XML文件来管理测试用例的分组和依赖关系。
14 2
|
3天前
|
存储 XML Java
探索Java常用的包:从核心到扩展
探索Java常用的包:从核心到扩展
12 3
|
3天前
|
运维 监控 Java
性能监控之 Java Metrics 度量包
【6月更文挑战10天】标题性能监控之 Java Metrics 度量包
27 2
|
5天前
|
XML 测试技术 数据格式
《手把手教你》系列基础篇(七十五)-java+ selenium自动化测试-框架设计基础-TestNG实现DDT - 中篇(详解教程)
【6月更文挑战第16天】本文介绍了TestNG中`@DataProvider`的两种使用方法。本文通过实例展示了TestNG如何利用`@DataProvider`结合方法名和`ITestContext`来灵活地为测试方法传递参数。
11 1
|
23小时前
|
Java
杨老师课堂_Java教程第二篇之变量及运算符
杨老师课堂_Java教程第二篇之变量及运算符
3 0
|
2天前
|
Oracle Java 关系型数据库
Java官网下载JDK21版本详细教程(下载、安装、环境变量配置)
Java官网下载JDK21版本详细教程(下载、安装、环境变量配置)
|
4天前
|
存储 测试技术 数据安全/隐私保护
《手把手教你》系列基础篇(七十六)-java+ selenium自动化测试-框架设计基础-TestNG实现DDT - 下篇(详解教程)
【6月更文挑战第17天】本文是一篇关于使用Selenium和TestNG进行数据驱动测试的教程。作者宏哥通过实例展示了如何处理多个用户登录场景。
37 0