private仅对本类可见,编译期拒绝跨类访问,子类和同包类均不可访问;封装需配合getter/setter实现业务逻辑控制,而非仅靠private修饰。
Java中private的可见性范围最窄:仅限声明它的那个类内部可访问,连子类、同包其他类、外部类都不行。这不是“限制访问”,而是“不提供访问入口”——编译器在编译期就直接拒绝任何跨类调用,不会生成对应字节码。
常见错误现象:javac报错error: cannot find symbol或error: xxx has private access in YYY,说明你试图从非本类位置读写private字段或调用private方法。
private成员,哪怕重写toString()时想调用父类private String name也不行obj.privateField,哪怕obj是该类实例private方法不能被反射绕过(除非显式调用setAccessible(true),但这属于破坏封装的非常规手段)把字段设为private只是第一步;真正完成封装,得靠公开的public或protected方法来控制读写逻辑。比如校验、懒加载、事件通知等,都只能在这些方法里加。
示例:
public class BankAccount {
private double balance;
public void deposit(double amount) {
if (amount > 0) { // 封装的逻辑在这里
balance += amount;
}
}
public double getBalance() {
return balance; // 不暴露原始字段,后续可加日志、缓存等
}
}
public double balance会导致余额被任意修改,失去业务约束deposit()设为private也没意义——外界根本调用不到,无法完成存款动作getXXX()/setXXX()是JDK、Jackson、Hibernate等框架默认识别的约定Java语法规定:private只能用于成员变量、方法、内部类(包括匿名类和局部类),不能修饰顶级类或接口。写private class A {}在文件顶层会直接编译失败。
错误示例:error: modifier private not allowed here
default(即不写修饰符),表示包私有private,例如private static class Helper {},此时只有外层类能实例化它public abstract,字段默认是public static final,加private会报错运行时JVM不强制检查private——它只是编译期约束。通过java.lang.reflect可以绕过,只要目标类没做安全管理器限制。
示例:
Field f = obj.getClass().getDeclaredField("balance");
f.setAccessible(true); // 关键一步:关闭访问检查
f.set(obj, 99999.0);
private状态;测试中慎用setAccessible(true),容易因字段名变更导致测试崩溃opens指令限制,未开放的包内private成员无法被外部模块反射访问
private切断了直连路径,但真正守住边界的,是你在getter/setter里写的那几行判断。