从clone()谈protected

看到Object的clone()是protected的,然后看到《java2认证考试指南》上描述:一个对象只能请求其他对象的克隆,后者的类与被克隆对象属于同一类,或是被克隆对象的子类。

example:   C-->B-->A <--D

C对象能克隆B或A对象;B对象能克隆A对象;D对象能克隆A对象

B对象不能克隆D对象

 

我是读了很久没有理解,最后读了一些程序才发现这样理解:主要是visibility问题。因为是protected的,那么在子类不重载,则自动继承。子类和父类在不同package时,子类实例可以调用它自己的protected foo(), 但在子类的code中调用父类实例的protected foo(),则看不见。 //子类中用父类对象反而不能访问父类中的protected变量  

之所以没能理解,原因居然是国内的很多Java书籍在介绍访问权限时,一般都这样描述:

 

 publicprotecteddefaultprivate
同类TTTT
同包TTT 
子类(不同包)TT  
无继承关系不同包的类T   

所以我们想当然的认为,B继承A,在不同包,那么在B的code中用A的实例a调用a.clone()是可以的,但是,事实上:不行(但b.clone显然可以)

这里给出《java in a nutshell》中的一段话:【让我理解了真正的protected-你不能在B中调用A的protected方法,你可以调用自己继承于A的那个protected方法】
protected access requires a little more elaboration. Suppose class A declares a protected field x and is extended by a class B, which is defined in a different package (this last point is important). Class B inherits the protected field x, and its code can access that field in the current instance of B or in any other instances of B that the code can refer to. This does not mean, however, that the code of class B can start reading the protected fields of arbitrary instances of A! If an object is an instance of A but is not an instance of B, its fields are obviously not inherited by B, and the code of class B cannot read them.
如果一个对象o是Object实例,但不是B的实例,在B的code中不能看到o.clone,就因为它是protected字段或方法(因此需要public)
因此上面表格第三行显然没有细化protected,它说可以访问应该是指可以使用super.funProtected()或自己实例的funProtected()

代码如下:

package test;

public class Tree{
    protected int age;
    
    void sayTree(){
        Maple mm=new Maple();
        mm.clone();//compile ok, mm is instance of Maple, also instance of Tree
    }
}

class Maple extends Tree{
    public void sayMaple(){
        Maple m=new Maple();
        m.age=0;
        
        Tree t=new Tree();
        t.age=0; //ok, same pack can access protected field
        
        m.clone();//compile ok, can access Maple's protected fun
        t.clone();//error, t is instance of Tree, but not instance of Maple!-----------见上文黑色粗体字
    }
}


package test.a;

import test.*;
class Pine extends Tree{
    public void say(){
        Pine p=new Pine();
        p.age=0;
        p.clone();
        
        Tree t=new Tree();
        t.age=0;                  // invisible
        t.clone();                // invisible
    }
}

 

转载于:https://www.cnblogs.com/jack-xu/p/4882944.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值