关于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方法根据重写的来计算可见性,未重写的像上追溯到有方法体的父类来计算可见性。