protexted访问修饰符,应该是访问修饰符中最难理解的一个修饰符.一般称之为受保护的访问权限.
其简单理解为protected修饰的成员对于本包和其子类可见.
但这不太够,往下可以引申为两点:
- 基类的protected成员是包内可见的,并且对子类可见;
- 若子类与基类不在同一包中,那么在子类中,子类实例可以访问其从基类继承而来的protected方法,而不能访问基类实例的protected方法。
解释:
-
在一个引用类,和被引用类在一个包的时候,protected成员是可见的(不管是不是子类)
-
子类如果不在一个包中,子类不能访问基类的protexted成员,但可以访问继承自基类的protexted成员
形象的解释一下这话,假设你知道你父亲私房钱放在什么地方.当你和你父亲住在一起的时候,你可以去拿你父亲的私房钱用,此时这个钱,根属于你的父亲(你母亲如果知道你父亲私房钱的地址也可以去拿来用),但是如果一旦你们分家,你和别的人组成了新的家庭,你就不可以直接去父亲家里拿钱用了.你能用的,只有你父亲给你的钱,也就是你继承的钱,这时候这个钱是根属于你的.
-
受保护,这三个字特别有意思,个人感觉,protected关键字的目的是为了保护数据只在同包和子类中能够被访问引用.就像是钱,这个玩意,只能一家人或者你的子女能够用,如果子女分家了,他们只能用自己继承了的钱.绝对不会有外人能够花这笔钱.
如何判断可不可用
光知道上面的定义,还不够,我们必须要还得了解怎么去判断,方法是:
- 确定出该protected成员来自何方,其可见性范围是什么,然后就可以判断出当前用法是否可行了
实例
这有几个网上的例子,我做了部分的修改,我们可以来分析一下
例子1
package family1;
public class Father {
protected void Money() {} // 父类Father1中的protected方法
}
package family1;
public class Son1 extends Father{}
package family1;
public class mother {
public static void main(String[] args) {
Son1 son1 = new Son1();
son1.Money(); // Compile OK ----(1)
son1.clone(); // Compile Error ----(2)
Son2 son = new Son11();
son2.Money(); // Compile OK ----(3)
son2.clone(); // Compile Error ----(4)
}
package family2;
public class Son2 extends Father{}
-
首先来看 (1)为什么成立? son1的Money,追溯到根源,是谁的钱?是father的钱.那问题来了,father和mother是一family1的中的.所以mother当然可以用father的money啊.所以(1)是成立的
-
(3)和(1)是同理,虽然 son2 和mother不在一个family了,son2找到了老婆,但son2的money不是自己找的,是来源于father的,所以mother当然能用了.
-
(2)为什么错? 首先 clone()方法object中的方法.所以任何类都继承于object.那为什么(2)错呢?mother和son1在一个family中,都继承了clone,但mother是去那了son2的clone,但clone最终来源并不是和mother在一个family.有点绕
搞个形象的解释.你父亲分别给了你和你兄弟没人一万块.结果你兄弟用完了钱,直接过来就把你的一万块给拿走了,你能够干?很明显不能,这钱是父亲给你的,你兄弟凭啥给你拿走,对吧?同理在(2)中 son2 的clone()是object给的,又不是mother给的,mother凭啥拿啊,就像你二舅要拿你爷爷给的压岁钱,你能给他?
-
(4)同理与(2)
例子2
package family1;
class father {
protected Object clone() throws CloneNotSupportedException{
return super.money();
}
}
package family2;
public class son extends father {
public static void main(String args[]) {
father fa = new father();
fa.money(); // Compile Error ----(1)
son s = new son();
s.money(); // Complie OK ----(2)
}
}
-
看这里例子,首先为什么(1)错误.解释是:若子类与基类不在同一包中,那么在子类中,子类实例可以访问其从基类继承而来的protected方法,而不能访问基类实例的protected方法。不够简单易懂,但是我们可以从另一个想一下,如果你现在没钱了,但你father有钱,那咋办呢?去找father要啊,但你要怎么去要money呢?
如果你直接把你father喊过来(实例化father对象),然后对他说,老头子,快给点钱花花,他能给吗?比不可能给啊
-
那要咋办呢?也就是第二种方法,你先明确自己的地位,自己是个son(实例化自己),然后好声好气的跟father要钱。也就是第二种方法,所以(2)是对的
-
二者的区别在于(1)方法是将自己当做外人,而(2)方法是将自己作为一家人。
-
需要注意的是,也可采用super.money去要钱,也是可以的