java默认访问权限(package-private)判断“同一包”仅依据源码中package声明是否完全一致,与物理路径无关;同包下任意类(含不同jar或模块)可直接访问default成员,无需继承或getter/setter。

Java中默认的包访问权限(即不写public、protected或private)叫package-private,它不是“私有”,而是“仅限同包可见”——这个“包”由源码中的package声明决定,不是文件夹路径。
它怎么判断“同一个包”?
只看类顶部的package语句,不看物理目录。比如:
-
A.java里写package com.example.util;,哪怕放在src/main/java/com/example/xxx/目录下,它的包名仍是com.example.util -
B.java也写package com.example.util;,哪怕在另一个JAR、另一个Maven子模块里,JVM就认为它和A在“同一个包” - 两个类package声明不同,哪怕物理上挤在一个文件夹,也完全不可见
它能被谁访问?
满足以下任一条件即可直接访问(无需getter/setter,也不需要继承):
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 同一个
package声明下的任意类(包括其他模块、其他JAR里的同名包) - 该类内部(自然可以)
- 注意:子类不行——哪怕子类继承了父类,只要不在同一包,就不能调用、重写或访问其default方法/字段
它不能防什么?常见误判点
很多人以为default=“锁死封装”,其实它非常轻量,几乎不设防:
-
反射可绕过:
field.setAccessible(true)后,任何地方都能读写default成员 - 同名包即同包:Maven多模块、OSGi、甚至不同Git仓库只要声明相同package,就能互相访问
-
不阻止new实例:default类可以被同包类直接
new,不像private类必须靠工厂 -
接口里不是default:接口中未加修饰符的方法默认是
public abstract(Java 8前)或public(默认方法/静态方法),和类的default规则完全不同
想真正封装?得升级手段
仅靠default做不到强封装,需结合更高层机制:
- JDK 9+ 模块系统:在
module-info.java中不exports对应包,外部模块连编译都过不去 - 工厂模式隔离:把实现类设为default或private,只暴露public static工厂方法,返回接口类型
- 构建期校验:用字节码分析工具(如Byte Buddy或ArchUnit)检查跨包非法引用
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










