Java访问权限之 protected 修饰符

摘要

        在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详解

Java protected 关键字详解

  • 4
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值