关于protected关键字:
java编程思想里面解释道:
关键字protected指明:
就类用户而言,这是private的,但对于任何继承于此类的导出类或其他任何位于同一个包内的类来说,它确是可以访问的.
这句话有两层含义:
1.父类的protected成员是包内可见的,并且对子类可见;
2.若子类与父类不在同一个包内,那么在子类中,子类实例可以访问其从父类继承而来的protected方法,而不能访问父类实例的protected方法;
我们通过以下的实例进行研究:
package p1;
public class Father1 {
protected void f() {} // 父类Father1中的protected方法
}
package p1;
public class Son1 extends Father1{
}
package p11;
import p1.Father1;
public class Son11 extends Father1 {
}
对于上面的示例,首先看(1)(3),其中的f()方法从类Father1继承而来,其可见性是包p1及其子类Son1和Son11,而由于调用f()方法的类Test所在的包也是p1,因此(1)(3)处编译通过。其次看(2)(4),其中的clone()方法的可见性是java.lang包及其所有子类,对于语句“son1.clone();”和“son11.clone();”,二者的clone()在类Son1、Son11中是可见的,但对Test1是不可见的,因此(1)(3)处编译不通过。
clone()方法在其子类是可见的,代码如下:
编译通过。
接下来再看一个代码:
package p1;
public class Father2 {
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
对于(1)而言,clone()方法来自于类Father2本身,因此其可见性为包p1及Father2的子类,虽然Test2是Father2的子类,但在Test2中不能访问基类Father2的protected方法clone(),因此编译不通过;对于(2)而言,由于在Test2中访问的是其本身实例的从基类Father2继承来的的clone(),因此编译通过。
换句话说:Test2和Father2不在一个包下,那么只有其子类实例能访问其从父类继承而来的clone()方法,其父类实例是不能访问自己的protected方法clone()。
总结:
判断protected方法的可见性的时候:
如果一个类A包含一个protected方法AA,那么:
1.需要访问的类和类A在一个包里面,那么它就可以访问类A的protected方法AA。
2.需要访问的类B和类A不在在一个包里面,那么只能是A的子类类B可以访问protected方法AA(继承下来的),类B里面的类A反而不能访问自己的protected方法AA了。更不用说是在类C的位置了。
我们用上述结论试试下面的场景,分析下原因:
首先clone()方法来自于java.lang包,java里面所有的类都默认继承自Object类,所以继承树是
MyObject7 extends Test7,Test7 extends Object,所以clone()在Test7类是可见的,因为Test7和Object不在一个包里面,那么在p3包里面,类Test7可以访问从object里面继承来的clone()方法,所以(3)处编译成功。
(1)这个地方,是Test7需要访问clone(),包不一样,可见性为Test7类里面,而且还不能new Object()去访问,但是你现在的访问地方是MyObject7里面,是没有这个权限的。
(2)这里是MyObject7去访问父类的clone()方法,具有访问权限。