Java学习之旅第二季-9:包

9.1 包的概念与作用

在项目开发中,将程序中相关的部分组合在一起通常很有帮助。在 Java 中,这可以通过使用模块/包来实现。本小节,我只关注包的使用。从Java 9 开始 JDK 中的 API 组织方式发生了很大变化,已经开始按照模块组织类、接口等了。不过为了向下兼容,开发不使用模块的 Java 项目时,可以不用关注模块,直接使用包即可。

通常来说,当我们为一个类命名时,就是在从命名空间中分配一个名称。命名空间定义了一个声明区域。在 Java 中,来自同一个命名空间的两个类不能使用相同的名称。因此,在给定的命名空间内,每个类名都必须是唯一的、独特的。

在大型项目中,为每个类找到独特的名称可能会很困难。此外还必须避免与其他在同一项目中工作的程序员所创建的代码以及 Java 库中的代码发生名称冲突。这些问题的解决方案就是包,因为它为开发人员提供了一种对命名空间进行划分的方法。当一个类定义在包内时,该包的名称会附加到每个类上,从而避免与具有相同名称但位于其他包中的其他类发生名称冲突。

由于一个包通常会包含相关的类,所以 Java 为包内的代码定义了特殊的访问权限。在一个包中,可以定义某些代码,使其仅能被同一包内的其他代码访问,而不能被包外的代码访问。

总结起来,包的作用有以下三点:

  • 相关功能的类可以以包的形式组织在一起,包内的类必须通过其包名来访问。因此,包提供了一种为类集合命名的方式
  • 不同的包中允许同名的类,这样有效避免了命名冲突
  • 包参与 Java 的访问控制机制。包内定义的类可以被设为仅在该包内可见,外部代码无法访问。因此,包提供了一种封装类的方法。

9.2 包的声明

在 Java 中,所有的类都属于某个包。如果没有指定包声明,就会使用默认包,默认包是没有名称的,默认的包适用于简短的示例程序,但对于实际应用来说则不够适用。通常情况下,我们会为代码定义一个或多个包。

要创建一个包,需在 Java 源文件的顶部添加一个 “package” 语句。该文件中声明的类将属于指定的包。

使用方式如下:

package com.laotan.article9;    // 包的声明

/**
 * @author 老谭
 */
public class PkgDemo {
}

上述代码中有几个注意的语法点:

  • 使用package关键字,在后面加上包名,该语句必须放在类文件的第一行(注释除外),且只能出现一次
  • 文件存放的位置一定与包名对应,如果使用IDEA等开发工具创建类,只有不手动移动文件位置,则一般不会出现不对应的情况

在开发中,对于包名的命名,一般有如下规则:

  • 不能以数字,特殊字符开头
  • 不能使用 Java 关键字
  • 所有的字母小写(约定俗成,不是语法要求的)
  • 采用域名反写,因为域名是全世界第一无二的,如果反写也是一样不可重复的

Java 是通过文件系统来管理包的,每个包都会被存储在单独的目录中。例如,我声明的包是 “com.laotan.article”,则此包的任何类文件必须存储在项目源码根目录的 “com/laotan/article” 的子目录中,而编译之后的 class 文件就存储在类路径下同名的目录中。简而言之,目录必须与包名完全一致。

公用部分名称并不会使两个包有关联,如 com.laotan 与 com.laotan.article 就是没有关联的两个包

9.3 JDK内置包

在JDK本身提供的API中,也是按照模块/包来自组织存放的,不考虑模块,以下是常见的包及描述:

包名描述
java.lang核心类,无需显式导入
java.util工具类,集合框架等
java.util.concurrent并发编程相关的API
java.io输入输出相关API
java.nio非阻塞IO相关API
java.net网络编程相关API
java.sql操作关系数据库的JDBC
java.time日期时间API
java.math数学计算相关API
javax.swingGUI开发相关API

9.4 类的导入

要使用不同包中的成员(以类为例),需要使用import关键字导入。

该语句出现在package语句后和类声明之前,且可以出现多次。

语法1:单类型导入

import pkg.ClassName;

语法2:通配符(Wildcard)导入

impotr pkg.*; //不允许出现多个*,且*只能在最后

语法3:静态导入

import static pkg.ClassName.staticMember; // 不能导入不同类中的同名静态成员

语法4:静态通配符导入

import static pkg.ClassName.*;

如果要使用的类是同一个包中或位于 java.lang 包中则不用显式导入,比如之前多次用到的 String 类。

9.5 类的导入顺序

正如之前提到的,包与目录是一一对应的。那么JVM如何知道去何处查找包呢?

首先,默认情况下,Java 运行时系统会将当前工作目录作为其起始点。因此,如果您的包位于当前目录的一个子目录中,那么它就会被找到。
其次,您可以通过设置 CLASSPATH 环境变量来指定一个或多个目录路径。

第三,您可以使用 java 和 javac 的 -classpath 选项来指定您的类的路径。需要指出的是,从 JDK 9 开始,一个包可以是模块的一部分,因此会在模块路径中被找到。不过,关于模块和模块路径的讨论将在第 15 章中进行。目前,我们将仅使用类路径。对于

  • 如果使用的是完整的类名,如:com.laotan.article9.ImportDemo,那么直接根据完整类名查找该类接口
  • 如果使用的是简单类名,如:ImportDemo,那么规则会复杂许多:
  1. 查找import语句是否导入了该类,如果导入了则使用
  2. 查找当前包是否存在该类,存在则直接使用
  3. 查找是否使用通配符导入了类所在的包,如果导入了则使用
  4. 查找 java.lang 中是否存在该类,如果存在则使用 java.lang 中的类

如果要使用不同包中同名的类,则可以使用全限定名使用该类

9.6 静态成员的导入顺序

  • 如果使用类访问静态成员,如:MyClass.staticMember,直接根据类名查找其成员
  • 如果直接使用静态成员,如: staticMember,则按照以下规则依次查找:
  1. 查找当前类是否声明了该静态成员,如果声明了直接使用
  2. 查找是否明确静态导入了其他类的该静态成员,如果导入了则使用
  3. 查找是否使用通配符静态导入了该成员所在的类,如果导入了则使用

9.7 package-info.java文件

在 Java 中,package-info.java 是包内的一个特殊文件,主要用于对包进行说明和配置,它的作用主要体现在以下几个方面:

  1. 包级别的文档注释(Javadoc):package-info.java 最常见的用途是为整个包编写文档注释。通过在该文件中使用 /** … */ 格式的注释,可以描述包的功能、用途、设计思路等信息,这些注释会被 Javadoc 工具提取并生成到 API 文档中,方便开发者理解包的整体作用
  2. 包级别的注解声明:可以在 package-info.java 中为整个包声明注解(需要注解的 @Target 包含 PACKAGE)。这些注解会作用于包内的所有类
  3. 可以在其中声明包内共用的类型,可以结合包级别访问控制限制其它包对其中类型的访问

注意事项

  • 创建 package-info.java 文件时,不能使用常规的Java类创建方法,因为文件名中包含了中划线,可以在IDEA中使用右键在包上创建

  • 文件名必须严格为 package-info.java,不能修改

  • 它必须放在对应的包目录下(与包内的类文件同级)

示例:

/**
 * 本包的代码用于演示包的语法
 *
 * @author 老谭
 */
package com.laotan.article9;

/**
 * 只有包内才能访问此类中声明的常量与方法
 */
class CommonClass {
    public static final String NAME = "摸鱼的老谭";

    public static String getName() {
        return NAME;
    }
}

9.8 小结

Java包机制是组织代码的重要方式,主要作用包括:组织相关类、避免命名冲突和实现访问控制。包通过目录结构管理,必须与包名严格对应。JDK API按功能组织在标准包中(如java.lang、java.util等)。使用import语句导入其他包的类,导入顺序遵循特定查找规则。静态成员导入使用import static语法。若遇到同名类冲突,需使用全限定名。包名通常采用反向域名命名法(如com.laotan.article)确保唯一性。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值