大家可能不太理解由Object.clone()而引出的protected权限问题这句话,那我们先看一段代码:
第一个类CloneClassOne
package com.ustc.sup;
public class CloneClassOne {
}
第二个类CloneClassTwo
package com.ustc.sup;
public class CloneClassTwo {
public static void main(String[] args) {
// TODO Auto-generated method stub
CloneClassOne one=new CloneClassOne();
one.clone();
Object object = new Object();
object.clone();
}
}
大家觉得这段代码有没有错呢?
答案:
one.clone();和object.clone();这两句提示The method clone() from the type Object is not visible
我们会有疑问:Object类是所有类的父类,那么为什么子类不能访问父类的protected修饰的方法呢?
“与基类不在同一个包中的子类,只能访问自身从基类继承而来的受保护成员,而不能访问基类实例本身的受保护成员”
例如:
父类Person在包com.ustc.sub;
package com.ustc.sub;
public class Person {
protected int a = 4;
protected int getA() {
return a;
}
}
子类Manager 、Student在包com.ustc.sup
package com.ustc.sup;
import com.ustc.sub.Person;
public class Student extends Person {
int getB()
{
return getA();
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Manager m = new Manager();
System.out.println(m.getB());
System.out.println(m.getA());//error
}
}
package com.ustc.sup;
import com.ustc.sub.Person;
public class Manager extends Person {
int getB()
{
return getA();
}
public static void main(String[] argr) {
Student s = new Student();
System.out.println(s.getB());
System.out.println(m.getA());//error
}
}
父类和子类不太一个包中,子类的方法getB()可以访问getA(),而实例s,m不能访问getA()方法。
我们都知道:protected 修饰的类和属性,对于自己、本包和其子类可见
但这样说你并不完全正确
对于protected的成员或方法,要分子类和超类是否在同一个包中。与基类不在同一个包中的子类,只能访问自身从基类继承而来的受保护成员,而不能访问基类实例本身的受保护成员。在相同包时,protected和public是一样的
接下来将一些实例,看完既可以完全理解protected权限了
例1
class MyObject {}
public class Test {
public static void main(String[] args) {
MyObject obj = new MyObject();
obj.clone(); // Compile error.
}
}
虽然MyObject与Test属于同一个包,但受保护的clone方法来自java.lang.Object类型,而在Test中,其基类Object的受保护方法是不可见的。
例2
class MyObject2 {
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class Test2 {
public static void main(String[] args) throws CloneNotSupportedException {
MyObject2 obj = new MyObject2();
obj.clone(); // Compile OK.
}
}
MyObject与Test在同一个包中,受保护的clone方法来自MyObject本身,所以它对Test而言是可见的。(在相同包时,protected和public是一样的)另外在这个示例中,还说明了super关键字对于基类受保护成员的调用是个语言设计之中的“例外”。
例3
package 1
class MyObject3 {
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
package 2
public class Test3 extends MyObject3 {
public static void main(String args[]) {
MyObject3 obj = new MyObject3();
obj.clone(); // Compile error.
Test3 tobj = new Test3();
tobj.clone();// Complie OK.
}
}
企图跨越不同的包,从子类中调用基类实例的受保护方法。明显不行。
例4
class MyObject extends Test{}
public class Test {
public static void main(String[] args) {
MyObject obj = new MyObject();
obj.clone(); // Compile ok.
}
}
可见呢?因为MyObject的clone方法继承自Test,而Test做为相对于Object的子类,是可以访问继承而来的属于它自己的受保护方法的。
例5
package 1
class MyObject extends Test {
}
package 2
public class Test {
public static void main(String args[]) {
MyObject obj = new MyObject();
obj.clone(); // Compile OK
}
}
虽然处于不同的包,但子类的受保护方法实际上继承自父类,父类的自己的受保护方法对自己可见,其原理同示例4.
例6
package 1
class MyObject extends Test {
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
package 2
public class Test {
public static void main(String args[]) {
MyObject obj = new MyObject();
obj.clone(); // Compile error!
}
}
不同包中子类本身的受保护方法当然不可能对父类可见
例7
package a;
class MyObject extends Test {
public static void main(String[] args) {
Test test = new Test();
test.clone(); // Compile error.
}
}
package a;
public class Test {
}
同一个包中,父类实例的clone方法在子类中依然不可见,原理同示例1,就是因为父类的clone方法,实际上来自java.lang.Object。
http://www.tuicool.com/articles/neURniJ