# 1)protected作用是什么?
假设我们有一个com.company包,其中有一个Vehicle类,它有一个protected String engineCode;字段。
// 文件:Vehicle.java
package com.company;
public class Vehicle {
protected String engineCode = "V8-001"; // 受保护的成员
}
1
2
3
4
5
6
2
3
4
5
6
# 规则 1)同包可见 - 如同一公司的同事
解释:只要在同一个包(com.company)里,不管有没有继承关系,其他类都能像访问公共成员一样访问这个protected成员。
// 文件:Mechanic.java
package com.company; // 关键:同一个包!
public class Mechanic {
public void repair(Vehicle v) {
// 可以直接访问,因为我们是“同事”,在同一个包工作
System.out.println("正在维修发动机型号:" + v.engineCode);
}
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
要点:Mechanic类和Vehicle类没有父子关系,但仅仅因为它们在同一包内,访问就被允许。
# 规则 2)子类可见 - 如同继承家业的子女
解释:即使子类搬到另一个城市(不同的包),它作为“亲儿子”,也天然拥有访问父亲(父类)家产(protected成员)的权利。但是,这个权利有明确的使用限制。
// 文件:com.customer.Car.java
package com.customer; // 关键:不同的包!
import com.company.Vehicle;
public class Car extends Vehicle { // 关键:Car是Vehicle的子类
public void displayCode() {
// ✅ 方式一:直接访问【自己继承来的】那份engineCode
System.out.println("我的发动机型号是:" + engineCode);
// ✅ 方式二:通过 `this` 访问
System.out.println("我的发动机型号是:" + this.engineCode);
}
public void checkOtherVehicle(Vehicle other) {
// ❌ 编译错误!不允许访问“别人家的”父类protected成员
// 即使“别人”(other)也是Vehicle或其子类,也不行。
// System.out.println(other.engineCode);
}
public void checkOtherCar(Car other) {
// ❌ 编译错误!同理,即使是同一类型的“兄弟”,也不行。
// System.out.println(other.engineCode);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
关键理解:
- 子类在另一个包中,能访问
protected成员吗?能! - 访问谁的呢?只能访问“属于自己这部分”的。即通过继承得到的、存储在自身对象(
this)中的那份protected成员。 - 不能随意查看其他对象的
protected成员。这就像你不能因为自己是富豪的儿子,就去随意查看另一个富豪儿子的银行账户一样。编译器通过这个限制来维护封装性。
# 一个生动的比喻
把包(package)想象成不同的公司或家族大院。
public(公共):就像街边的公共广告牌,谁都能看。protected(受保护):- 对本公司(同包)的所有员工(类)公开,可以随便看。
- 对本公司创始人的亲生子女(子类),即使他们搬出去自立门户(不同包),也保留了查看家族内部资料(
protected成员)的权利,但仅限于查看他们自己继承的那一份,不能去翻看其他兄弟姐妹家里的那份。
default(包私有):仅对本公司(同包)员工公开。离开公司的子女(不同包子类)也无权查看。private(私有):只有创始人自己(当前类)能看,连员工和子女都不能看。
# 总结表格
| 访问位置 | 能否访问 Vehicle 的 protected 成员? | 原因 |
|---|---|---|
同包非子类(如Mechanic) | ✅ 可以 | 规则1:同包可见 |
不同包子类内部访问this.xx(如Car中的this.engineCode) | ✅ 可以 | 规则2:子类可见 + 访问自身继承的部分 |
不同包子类访问另一个实例的xx(如car1.engineCode) | ❌ 不可以 | 虽然“子类可见”,但权限仅限于自身对象,不能访问其他不相关实例的受保护成员。 |