理解包的核心作用:组织代码、避免命名冲突、控制访问权限
掌握 内置包 与 用户自定义包 的使用方式
能够正确设计项目包结构并合理使用 import
理解包与 访问修饰符(public / protected / default / private) 的协同机制
包(Package) 是 Java 提供的一种命名空间机制,用于将相关的类、接口、枚举和子包组织在一起。
核心目的:
避免类名冲突(如两个项目都有
Utils类)控制类和成员的可见性
提升代码的模块化与可维护性
类比理解:文件夹
就像电脑中的文件夹:
Documents/Work/Report.docx
Documents/Personal/Letter.docx
即使文件名相同(Report.docx vs Letter.docx),路径不同就不会混淆。Java 包就是类的“路径”。

Java 中的包分为两类:
示例:使用 java.util.Random
import java.util.Random; // 导入内置包中的 Random 类
public class Main {
public static void main(String[] args) {
Random rand = new Random();
int number = rand.nextInt(100); // 生成 0~99 的随机整数
System.out.println("随机数: " + number);
}
}
java.lang下的所有类(如String,System)无需import即可直接使用。
// 文件路径: src/com/myapp/Helper.java
package com.myapp;
public class Helper {
public static void show() {
System.out.println("来自 Helper 的问候!");
}
}包名规范:
全小写
通常使用公司域名倒写:
com.company.project.module如:
com.alibaba.fastjson,org.apache.commons
project/
└── src/
└── com/
└── myapp/
├── Helper.java
└── Test.java重要:包名必须与文件系统目录结构完全一致!
// 文件: src/com/myapp/Test.java
package com.myapp;
// 方式1:导入具体类
import com.myapp.Helper;
public class Test {
public static void main(String[] args) {
Helper.show(); // 输出:来自 Helper 的问候!
}
}或使用全限定名(不推荐,冗长):
public class Test {
public static void main(String[] args) {
com.myapp.Helper.show();
}
}示例对比
// 方式1:精确导入
import java.util.Vector;
import java.util.ArrayList;
public class Example {
Vector v = new Vector();
ArrayList list = new ArrayList();
}// 方式2:通配符导入(慎用)
import java.util.*;
public class Example {
Vector v = new Vector();
ArrayList list = new ArrayList();
}不推荐通配符导入的原因:
可能引发类名冲突(如
java.util.Listvsjava.awt.List)降低代码可读性(不清楚具体用了哪些类)
包直接影响类成员的可见性范围。以下是四种访问级别在包中的表现:
关键点解析
default(包私有):
只有同一个包内的类可以访问。这是实现“包内协作,对外隐藏”的关键。
protected:
同包 + 所有子类(即使子类在其他包)都能访问。
示例:default 访问控制
// 包: com.myapp.utils
package com.myapp.utils;
class InternalUtil { // default 访问权限
static void helper() {
System.out.println("内部工具方法");
}
}
// 同包下的另一个类可以访问
class PublicAPI {
void doSomething() {
InternalUtil.helper(); // 允许
}
}// 包: com.other
package com.other;
import com.myapp.utils.InternalUtil;
public class External {
void test() {
// InternalUtil.helper(); // 编译错误!InternalUtil 不可见
}
}这正是包提供“访问保护”的体现。
使用反向域名:com.google.gson, org.springframework.boot
全小写,避免下划线 / 大写:
✅ com.example.service
❌ Com.Example.Service 或 com_example_service
按功能分层:
com.mybank
├── model // 数据模型
├── service // 业务逻辑
├── repository // 数据访问
└── controller // Web 控制器避免使用 Java 保留包名:
不要使用 java.*, javax.*, sun.* 等
用于直接导入类的静态成员,避免重复写类名。
import static java.lang.Math.*;
import static java.lang.System.out;
public class MathExample {
public static void main(String[] args) {
double result = sqrt(pow(3, 2) + pow(4, 2)); // 直接调用 sqrt, pow
out.println("结果: " + result); // 使用 out 代替 System.out
}
}谨慎使用:过度使用会降低代码可读性。
包是 Java 的命名空间 + 模块化单元
内置包(如 java.util)提供标准功能,用户包用于组织自有代码
包名 = 目录结构,必须严格对应
import 用于引入其他包中的类,推荐精确导入
default 访问修饰符实现“包内可见”,是封装的重要手段
合理的包结构提升项目的可维护性、可读性与安全性
为什么 java.lang 包不需要显式 import?这对开发者有什么好处?
如果两个不同包中有同名类(如 com.a.Util 和 com.b.Util),如何在同一个文件中同时使用它们?
为什么说“包 + default 访问控制”是实现模块内部协作而不暴露细节的有效方式?