本期是Java开发教程系列的第四期,本期主要向各位介绍访问控制——规定类里的成员能被谁访问.若你已经熟悉四种访问级别[public/protected/包私有(package-private)/private],可以跳过本期内容.
每期叠甲:
时间仓促,水平有限,文中难免存在缺点和错误,恳请广大开发者和从业者指正.
一、为什么要控制访问
第 3 期我们为了让跨包能用,把字段和方法都标了 public.但全部 public 有问题:
public class Student {
public double score;
}
Student s = new Student();
s.score = -80; // 成绩居然是负数?!
成绩为负明显不合理.可字段是 public 的,任何代码都能随便改,拦不住.
访问控制就是为了解决这个问题:规定类里的每个成员能被谁访问.把不该让别人乱动的数据藏起来,只留几个安全的口子让外面用——这个"藏起来"的做法叫封装,下一期专门讲,本期先把"谁能访问谁"这张规则表讲透.
二、四种访问级别
Java 的成员有四种访问级别,从"最开放"到"最封闭":

用一张"同包/子类/任意位置"的表格更清楚:

记忆口诀:越往后越封闭.
四个级别从"完全公开"到"完全私有",一行一行对比着记,别死背.
三、动手验证:访问边界实验
光看表容易忘,亲手让编译器报几次错就记住了.做一个两个包 + 一个子类的小实验.
目录结构:
codes/
└── src/
├── com/mycodes/model/ ← 包 com.mycodes.model
│ ├── Student.java
│ └── StudentSub.java ← 子类,在另一个包
└── com/mycodes/app/ ← 包 com.mycodes.app
└── Main.java
文件一 com/mycodes/model/Student.java:
package com.mycodes.model;
public class Student {
public String name; // public:任何地方都能访问
String nickname; // 默认:只有同包能访问
private String secret; // private:只有本类能访问
protected void printDetail() { // protected:同包 + 子类
System.out.println(name + "(" + nickname + ")");
}
}
文件二 com/mycodes/model/StudentSub.java(不同包的子类):
package com.mycodes.model;
public class StudentSub extends Student {
public void test() {
System.out.println(name); // public,子类能用
System.out.println(nickname); // 同包(子类和父类同包)
// System.out.println(secret); // private,子类也碰不到
printDetail(); // protected,子类能用
}
}
文件三 com/mycodes/app/Main.java(同包外、非子类):
package com.mycodes.app;
import com.mycodes.model.Student;
public class Main {
public static void main(String\[\] args) {
Student s = new Student();
System.out.println(s.name); // public,跨包也能用
// System.out.println(s.nickname); // 默认,跨包不能用
// System.out.println(s.secret); // private,更不能
// s.printDetail(); // protected,跨包且不是子类
}
}
动手验证:把每处注释掉的代码一行一行放开,编译,看报错——报错信息会直说"访问权限不足".全部放开的报错顺序,正好就是表格从右往左读一遍.看完报错再把代码注释回去,项目就能跑.
朝花夕拾:第 3 期留的半个规则,本期补全了
第 3 期我们只讲了两个:public 任何地方能访问、默认只有同包能访问,当时说"完整的四种访问级别下一期专门讲".现在四档齐了:
protected 比默认多的口子:不同包的子类
private 比默认少的口子:连同包都不行
记住一个关系图:public > protected > 默认 > private.第 3 期你写的 public class Student + public 字段,今天开始,字段就可以放心地往"更封闭"的方向收了.
总结
本期把"谁能访问谁"讲清楚了:
下一期我们学习封装与 static——用 private + getter/setter 把数据保护起来,再认识"属于类而不属于对象"的 static.