Java:由Object.clone()而引出的protected权限问题

Object.clone()

大家可能不太理解由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的成员或方法,要分子类和超类是否在同一个包中。与基类不在同一个包中的子类,只能访问自身从基类继承而来的受保护成员,而不能访问基类实例本身的受保护成员。在相同包时,protected和public是一样的
这里写图片描述

  • Class SubB has
    access only to the inherited from Base protected elements,
    i.e. its own elements, but the protecteddata of other Base instances
    is not accessible from SubB.

接下来将一些实例,看完既可以完全理解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

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页