JAVA protected关键字可见性详解

关于JAVA的可见性关键字大家一定都不陌生,但是最近突然发现自己对protected的认识不是很全面,于是写了demo好好的研究下。

先简单介绍下各关键字的可见性(图是从网上找的):


表格基本说明了各个关键字的可见范围,但是protected需要单独拿出来说下。

先来个例子:

package it;
public class Testing {
    protected int t1;

}

package it;
public class test2 {
    public test2() {
        Testing mTesting = new Testing();
        mTesting.t1 = 2;   //ok
    }
}

在这里test2是可以访问到Testing 中的t1的,根据上面的表因为他们在一个包里。需要注意的是这里test2是不是Testing的子类

可以说是毫无影响,因为他们只要在一个包里就可以访问到了。

那接下来再来一个类:

package he;
import it.Testing;
public class test3{
    public test3() {
        Testing mTesting = new Testing();
        mTesting.t1 = 1;//error
    }

}

这个自然访问不到,既不是Testing子类也不是同一个包里。

好,那我们把他改为这样呢。

package he;
import it.Testing;
public class test3 extends Testing {
    public test3() {
        Testing mTesting = new Testing();
        mTesting.t1 = 1;//error
    }

}

纳尼!使他继承Testing为何还是error,难道表格错了?

其实这里就是重点了,当父类和子类不在同一个包中时,父类中protected修饰的变量和方法是不可以被子类访问的!

那表格里说的子类可见是什么意思呢?我们改下这个类

package he;
import it.Testing;
public class test3 extends Testing {
    public test3() {
        t1 = 1;//ok
    }

}

原来如此,protected修饰的变量和方法会被子类继承,但是子类也只可以访问自己继承而来的方法和变量,不可以访问父类的。(在不是同一个包的情况下,同包可以访问)

这里还有一点需要说明,就是关于重写父类的protected方法

再次举栗:

因为所有的类都是继承自object,并且有一个protected的clone方法。

package it;
public class Testing {
    protected int t1;

}

package it;
public class test2 {
    public test2() {
        Testing mTesting = new Testing();
        try {
            mTesting.clone();//error
        } catch (CloneNotSupportedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

这样test2中是不能访问的,clone方法在object的类中,根据我们上面说的,test2不和object的同一个包访问不到。

但是,改下

package it;
public class Testing {
    protected int t1;
    @Override
    protected Object clone() throws CloneNotSupportedException {
        // TODO Auto-generated method stub
        return super.clone();
    }

}

package it;
public class test2 {
    public test2() {
        Testing mTesting = new Testing();
        try {
            mTesting.clone();//ok
        } catch (CloneNotSupportedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

也就是重写clone后访问clone方法实际是访问的Testing的,因此是可见的(同包)。

那最后的一种情况

package it;
public class Testing {
    protected int t1;
    @Override
    protected Object clone() throws CloneNotSupportedException {
        // TODO Auto-generated method stub
        return super.clone();
    }

}


package he;

import it.Testing;
public class test3 extends Testing {
    public test3() {
        Testing mTesting = new Testing();
        try {
            clone();//ok
            mTesting.clone();//error
        } catch (CloneNotSupportedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

根据上面的内容不难得到这个结果。

总之还是这句话:在不是同一个包的情况下,protected修饰的变量和方法会被子类继承,但是子类也只可以访问自己继承而来的方法和变量,不可以访问父类的(同包可以访问)。重写的protected方法根据重写的来计算可见性,未重写的像上追溯到有方法体的父类来计算可见性。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值