Java包是组织代码和控制访问权限的命名空间机制,通过package声明归属、import导入使用,并与public/protected/默认/private共同实现细粒度可见性管理。

Java 的包机制既是组织代码的逻辑结构,也是访问权限控制的基础工具。它通过命名空间隔离类,同时配合 public、protected、默认(包级)和 private 四种访问修饰符,实现细粒度的可见性管理。
用包声明明确类的归属
每个 Java 源文件顶部用 package 语句声明所属包,必须是文件中第一条可执行语句(注释除外)。包名通常使用小写字母,按域名反写(如 com.example.utils),对应文件系统中的目录层级。
- 编译时,
javac会将类文件输出到与包路径匹配的子目录中(例如com/example/utils/StringUtils.class) - 运行时,JVM 依赖类路径(
-cp)定位包内类;若目录结构与包声明不一致,会抛出NoClassDefFoundError - 同一包下的类可直接相互访问——即使没有
public修饰,也能调用彼此的默认访问成员
四种访问修饰符的实际作用范围
访问控制不仅取决于修饰符本身,还受包关系影响:
- public:任何位置都可访问(跨包、跨类、子类)
-
protected:本包内所有类 + 不同包中的子类(注意:子类对象不能访问父类
protected成员的“其他实例”,只能访问自身继承来的) - 默认(无修饰符):仅限本包内访问,与是否继承无关
- private:仅限本类内部访问,不对外暴露
例如:com.example.model.User 中一个 protected void updatePassword() 方法,在 com.example.service.UserService(同包)中可直接调用;在 org.test.AdminUser(不同包但继承 User)中也能调用,但不能通过 new User().updatePassword() 调用。
立即学习“Java免费学习笔记(深入)”;
用 import 简化跨包引用
要使用其他包中的 public 类,需用 import 导入。有三种常见方式:
- 单类型导入:
import java.util.ArrayList; - 静态导入(用于常量或工具方法):
import static java.lang.Math.PI;或import static org.junit.Assert.assertEquals; - 通配符导入:
import java.util.*;—— 仅导入该包下public类,不递归子包;建议避免在生产代码中滥用,易引发命名冲突且降低可读性
注意:java.lang 包自动导入,无需显式声明;自定义包必须手动导入才能使用其中的 public 类。
包私有设计与模块化演进
包级访问(默认修饰符)是封装的重要手段。例如工具类中的核心算法方法设为默认访问,只允许同包内的公共 API 类调用,外部用户只能通过 public 门面类间接使用。
- JDK 9 引入模块系统(
module-info.java),可在包基础上进一步限制哪些包对其他模块可见(exports)、哪些模块可被依赖(requires) - 模块不是包的替代,而是更高层的封装单位;一个模块可包含多个包,但模块声明必须显式导出需要对外暴露的包
- 未声明模块的项目仍按传统包机制运行,兼容性良好
不复杂但容易忽略:包名拼写错误、目录结构不匹配、遗漏 public 修饰导致跨包无法访问——这些是新手最常见的编译失败原因。


















