摘要
在Java中,使用访问权限修饰符来保护对类、变量、方法和构造方法的访问,这类修饰符分别是public,protected,default,以及private。由于很多Java书籍对protected可见性的介绍都比较笼统,本文重点说明protected的权限
一、Java权限访问修饰符
各访问修饰符权限如下:
同一个类中 | 同一个包内 | 不同包的子类 | 不同包的其他类 | |
public | ✔ | ✔ | ✔ | ✔ |
protected | ✔ | ✔ | ✔* | |
default | ✔ | ✔ | ||
private | ✔ |
在上面所提到的四种修饰词中,除 protected 外都很好理解和掌握,在此略作简述:
- public :能被所有的类访问。
- default :只能被同一包中的类访问。
- private :只能在定义它的类中被访问,其他类都访问不到。
二、protected关键字的可见性
很多介绍Java语言的书籍(比如《Java编程思想》)都对protected做了介绍,但是描述的比较简单,基本都是一句话“被protected修饰的成员对于本包和其子类可见”。这种说法有点太过含糊,常常会对大家造成误解。实际上,protected的可见性在于以下几点:
- 基类的protected成员在同一个包内可见。
- 若子类与基类不在同一包中,那么在子类中,子类实例可以访问其从基类继承而来的protected方法,而不能访问基类实例的protected方法。
- 不管是否在一个包中,在基类,都可以通过子类实例访问继承的来自父类的protected方法。
- 若子类与基类不在同一包中,那么在基类中,不能通过子类实例访问(父类中没有)子类中特有的protected修饰的成员。
接下来我们通过下面几个关于protected方法可见性的例子进行详细解释protected关键字:
示例一:
package p1;
public class Father1 {
protected void f() {} // 父类Father1中的protected方法
}
package p1;
public class Son1 extends Father1 {}
package p11;
public class Son11 extends Father1{}
package p1;
public class Test1 {
public static void main(String[] args) {
Son1 son1 = new Son1();
son1.f(); // Compile OK ----(1)
son1.clone(); // Compile Error ----(2)
Son11 son = new Son11();
son11.f(); // Compile OK ----(3)
son11.clone(); // Compile Error ----(4)
}
}
- 首先看(1) (3),其中f()方法从类Father1继承而来,其可见性是包p1及其子类Son1和Son11,而由于调用f()方法的类Test1所在的包也是p1,同一个包内可见,因此(1)(3)处编译通过。
- 其次看(2) (4),其中clone()方法所在类为Object默认根类,而Object类所在包为java.lang包。其可见性是java.lang包及其所有子类,对于语句“son1.clone();”和“son11.clone();”,二者的clone()在类Son1、Son2中是可见的(可以使用的),但在Test类是不可见的,因此(1)(3)处编译不通过
示例二:
package p2;
public class Father2 {
protected Object clone() throws CloneNotSupportedException{
return super.clone();
}
}
package p22;
import p2.Father2;
public class Son2 extends Father2 {
public static void main(String args[]) throws CloneNotSupportedException {
Father2 f2 = new Father2();
f2.clone(); // Compile Error ----(1)
Son2 son2 = new Son2();
son2.clone(); // Complie OK ----(2)
}
}
- 对于(1)而言,clone()方法来自于类Father2本身,因此其可见性为包p2及Father2的子类,虽然Son2是Father2的子类,但在Son2中不能访问基类Father2的protected方法clone(),因此编译不通过;
- 对于(2)而言,由于在Son2中访问的是其本身实例的从基类Father2继承来的的clone(),因此编译通过。
示例三:
package p3;
import p33.Son3;
public class Father3 {
public static void main(String[] argv) throws CloneNotSupportedException {
Son3 son3 = new Son3();
son3.clone(); // Compile OK ------(1)
}
}
package p33;
import p3.Father3;
public class Son3 extends Father3 {}
- 不管是否在同一个包中,在基类中,可以通过子类实例访问继承的来自基类的protected方法。(当然,基类clone()方法,也是继承自java.lang.Object))
示例四:
package p4;
import p44.Son4;
public class Father4 {
public static void main(String[] argv){
Son4 son4 = new Son4();
son4.clone(); // Compile Error -----(1)
}
}
package p44;
import p4.Father4;
public class Son4 extends Father4 {
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
- 在基类中,不能通过子类实例访问(基类中没有)子类中特有的protected修饰的成员。
示例五:
package p5;
public class Father5 {
protected Object clone() throws CloneNotSupportedException{
return super.clone();
}
}
package p5;
public class Test5 {
public static void main(String[] args) throws CloneNotSupportedException {
Father5 f5 = new Father5();
f5.clone(); // Compile OK ----(1)
}
}
- clone() 方法来自类Father5,其可见性为包p5 及其子类。
示例六:
package p6;
public class Father6 {
public static void main(String[] args) throws CloneNotSupportedException {
Son6 son6 = new Son6();
son6.clone(); // Compile OK -------(1)
}
}
class Son6 extends Father6{}
- 不管是否在同一个包中,在基类中,可以通过子类实例访问继承的来自基类的protected方法。(当然,父类clone()方法,也是继承自java.lang.Object))
示例七:
package p7;
public class Father7 {}
class Son7 extends Father7{
public static void main(String[] args){
Father7 f7 = new Father7();
f7.clone(); // Compile Error ----- (1)
}
}
- clone方法来自于java.lang.Object,可见性为java.lang这个包和对应继承了这个clone()方法的子类,及Father7类中。
三、引用
Java基础知识详解: protected修饰符
Java访问权限之 protected详解文章来源:https://www.toymoban.com/news/detail-744786.html
Java protected 关键字详解文章来源地址https://www.toymoban.com/news/detail-744786.html
到了这里,关于Java访问权限之 protected 修饰符的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!