无法理解Java接口下的类行为:子类访问父类成员异常问题
搞懂Java接口修改后你的类行为变化
首先得先帮你理清两个场景的核心差异,顺便纠正一个你可能没注意到的小细节~
先拆解你的两段代码逻辑
最初的接口写法
你一开始的代码是这样的:
interface BankTransaction { void transcation(); } // 注意这里方法名拼错了!正确是transaction class Customer { protected double rate; //do something } class CurrentAccount extends Customer implements BankTransaction { private double x; // do something public void transcation() { // 你说x无法访问rate x = rate * 1 / 100; } }
先划重点:从Java语法上来说,这段代码里CurrentAccount完全可以直接访问rate!因为CurrentAccount继承了Customer,而rate是protected修饰的——子类本来就有权限访问父类的protected成员。你觉得“无法访问”,大概率是因为那个方法名拼写错误(transcation应该是transaction),导致编译器认为你没正确实现接口,报错信息让你误以为是rate的访问问题,或者是rate没初始化导致运行时出问题,而非访问权限的问题。
修改后的接口写法
当你把接口改成带参数的版本:
interface BankTransaction { void transaction(Customer c); }
然后实现方法变成:
public void transaction(Customer c) { x = c.rate * 1 / 100; }
这时你是通过传入的Customer对象来访问rate,这和第一种场景是完全不同的访问逻辑:
- 第一种场景里的
rate等价于this.rate,是当前CurrentAccount对象自己继承来的父类成员,属于子类对自身内部属性的访问。 - 第二种场景里的
c.rate是访问任意Customer实例的rate——这个实例可以是另一个CurrentAccount、SavingsAccount(如果有的话),甚至是直接创建的Customer对象,只要它是Customer类型就行。
为什么你会觉得第一种场景有问题?
大概率是这两个坑之一:
- 方法名拼写错误:你代码里把
transaction写成了transcation,编译器会认为你没有实现接口要求的transaction()方法,抛出错误,你可能把这个错误和rate的访问问题混淆了。 rate未初始化:Customer里的rate没有赋值,默认是0.0,计算出来的x是0,但这不是“无法访问”,是变量值的问题。
两种访问方式的本质区别
简单说:
- 场景1:你在操作自己这个对象的
rate,因为你本身就是Customer的子类,自带这个属性。 - 场景2:你在操作别人给你的某个
Customer对象的rate,这个对象和你自己可以是完全不同的实例。
如果第一种场景真的出现了编译层面的“无法访问”错误,再检查下:
Customer和CurrentAccount是不是在不同的包下?不过就算跨包,子类也能访问父类的protected成员,这个可能性很低。- 是不是不小心把
rate的修饰符改成private了?你写的是protected,所以没问题。
内容的提问来源于stack exchange,提问作者user9441808
相关产品推荐
相关产品推荐

