Java包机制通过“命名空间+路径约束”双轨设计杜绝同名类冲突,类的唯一身份是全限定名(如com.example.order.User),包名须用反向域名规范,import仅为编译期语法糖,访问控制需包与修饰符协同实现。

Java 的包机制通过“命名空间+路径约束”双轨设计管理类,从根源上切断同名类冲突的可能。它不靠人工改名或规避,而是让相同类名在不同包中天然成为不同类型。
包就是类的唯一身份证
每个类的真正身份不是 User,而是全限定名,比如 com.example.order.User 和 com.example.payment.User。JVM 只认这个带路径的完整名字,两个 User 完全无关——就像“杭州西湖区的李四”和“成都武侯区的李四”,地址不同,人就不重。
- 声明
package com.example.order;,就必须把文件放在com/example/order/目录下 - 编译器、类加载器、IDE 全部按这个路径找类,错一丁点就报 class file contains wrong class
- 没有 package 声明的类属于默认包,不能被其他包 import(JDK 14+ 已禁止)
包名设计决定冲突是否发生
包名不是随便起的标签,它是防冲突的第一道防线。推荐用反向域名打底,再叠加业务层级:
- ✅ 推荐:
com.myorg.ecommerce.checkout.api(清晰、唯一、可读) - ❌ 避免:
util、common、test这类单层宽泛名,容易重复且语义模糊 - ❌ 禁止:
java.xxx或javax.xxx开头,会与 JDK 冲突 - 包之间没有父子关系:
com.a和com.a.b是两个完全独立的命名空间
import 不是“导入类”,只是写代码时的快捷方式
import 语句本身不加载类、不改变运行逻辑,纯属编译期语法糖。删掉所有 import,全部改用全限定名,程序照样编译运行。
立即学习“Java免费学习笔记(深入)”;
- 只用一个同名类:直接
import com.example.dto.User;,后面写User u = new User(); - 要用多个同名类:只能
import其中一个,另一个必须写全限定名,如new com.example.domain.User() - 绝对不要
import com.example.dto.*;和import com.example.domain.*;同时存在——编译器立刻报 The type User is ambiguous - 静态 import 也一样:
import static java.lang.Math.*;和import static org.junit.jupiter.api.Assertions.*;共存时,若都有assertEquals,就得显式写全名
封装和访问控制靠包 + 修饰符协同实现
包机制本身不控制可见性,但它和访问修饰符一起构成封装基础:
-
public类可被任意包 import 并使用(前提是类路径可达) - 不加修饰符(即包级私有)的字段或方法,仅对同一包内类可见——就算你 import 了那个类,也访问不到它的默认成员
-
protected成员对同包子类和不同包子类都可见,import 不影响这一规则 - 建议:核心 API 设为
public,内部工具类用默认访问,把实现细节锁死在包内


















