您好,欢迎来到九壹网。
搜索
您的当前位置:首页Protected深入理解

Protected深入理解

来源:九壹网
Java中的访问控制修饰符有四个级别,但属protected最复杂。如果问大家,protected修饰符作用,大家会说“在子类与同包中可以访问这个成员”,当然在自己类中也是可的,但你真的理解了吗?不信,先看看下面这些实例,看你是否也是这样想的(其中注释掉的是不能编译的): Java代码 package pk1.a; public class Base { protected int i = 1; protected void protect() {

System.out.println(\"Base::protect\"); } }

package pk1.a; import pk1.b.Sub;

public class SubSub extends Sub { void g() {

Sub s = new SubSub(); //!! s.protect();//规则2.c.i System.out.println(s.i);//规则2.c.ii } }

package pk1.b; import pk1.a.Base;

public class Sub extends Base { private void prt() {} protected void protect() {

System.out.println(\"Base::protect\"); }

void f() { //规则2.a this.protect(); this.i = 2;

//规则2.b

Base a2 = new Sub();

//!! a2.protect();

//!! System.out.println(a2.i);

//规则1

Sub b = new Sub(); b.protect(); b.i = 1; b.prt(); } }

package pk1.b;

public class SubSub extends Sub { void g() {

Sub s = new SubSub(); s.protect();//规则2.c.i

//!! System.out.println(s.i);//规则2.c.ii } }

package pk1.c; import pk1.a.Base; import pk1.b.Sub;

public class SubSub extends Sub { void g() {

this.protect();//规则2.a

//规则2.b

Base b = new SubSub(); //!! b.protect();

//!! System.out.println(b.i);

//规则2.b

Sub s = new SubSub(); //!! s.protect();

//!! System.out.println(s.i);

} }

Java代码 package pk2.a; public class Base { protected int i = 1;

protected void protect() {

System.out.println(\"Base::protect\"); } }

package pk2.a; import pk2.b.Sub; public class Other { void g() { //规则3.a

Base b = new Sub(); b.protect();

System.out.println(b.i);

//规则3.b.ii Sub s = new Sub(); s.protect();

System.out.println(s.i); } }

package pk2.b; import pk2.a.Base; public class Other { void g() { //规则3.a

Base b = new Sub(); //!! b.protect();

//!! System.out.println(b.i);

//规则3.b.ii Sub s = new Sub(); //!! s.protect(); //!! System.out.println(s.i); } }

package pk2.b; import pk2.a.Base;

public class Sub extends Base {}

Java代码 package pk3.a; import pk3.b.Sub; public class Base { protected int i = 1; protected void protect() {

System.out.println(\"Base::protect\"); }

static protected int i_s = 1; static protected void protect_s() {

System.out.println(\"Static:Base::protect\"); }

void f() {

//!! Sub.i_s = 2; //规则3.b.i Sub.protect_s();//规则3.b.ii } }

package pk3.a; import pk3.b.Sub; public class Other { void g() {

Sub s = new Sub();

//!! s.protect();//规则3.b.i System.out.println(s.i);//规则3.b.ii }

void f() {

//!! Sub.i_s = 2; //规则3.b.i Sub.protect_s();//规则3.b.ii

Base.i_s = 2;//规则3.a Base.protect_s();//规则3.a } }

package pk3.b; import pk3.a.Base; public class Other { void f() {

Sub.i_s = 2;//规则3.b.i

//!! Sub.protect1();//规则3.b.ii

//!! Base.i1 = 2;//规则3.a //!! Base.protect1();//规则3.a } }

package pk3.b; import pk3.a.Base;

public class Sub extends Base { protected void protect() {

System.out.println(\"Base::protect\"); }

static protected int i_s = 2;

void f() {

/*

* 在子类中可能通过子类类型或父类类型来来访问父类中protected静态

* 成员,而不管子类与父类是否在同一包中,或是子类重新定义了这些成员

*

* 注,在父类或子类中访问时后面的规则不再适用 */

System.out.println(Sub.i_s);//2 Sub.protect_s();

System.out.println(Base.i_s);//1 Base.protect_s(); } }

如果你看到这里,想法与程序一致的话,说明你理解了,如果不理解,那看看我的理解吧:

定义规则前,我这里约定有三个类,一个是Base类,一个是Base类的子类Sub类,一个是Sub类的子类Sub Sub类,另一个是Other类且与Base、Sub、Sub Sub没有继承关系,并假设Base中有protected方法与属性,都叫YYY吧。

在理解protected规则:首先要搞清楚什么叫访问?这里在讲到的访问是有二种的:

一、就是在类中通过“XXX x = new XXX(); x.YYY;”的形式来访问(不妨叫此种形式为“外部访问”吧,此种访问形式除了可以应用到自己与子类中外,还可以应用在其他类中访问,其中XXX表示定义的类型,这里可为Base与Sub、SubSub,YYY为方法或属性);

二、就是this.YYY的形式来访问(不妨叫此种形式为“内部访问”吧,不过这种访问形式只能应用在在自己的类或是子类中)。

protected方法与属性可访问的地方有三个:

1.在自己的类Base中:上面的“XXX x = new XXX(); x.YYY;”与“this.YYY”两种访问形式都可以访问的到自己定义的portected方法或属性; 2.二是子类Sub、SubSub中,这要分三种访问方式:

a. 在Sub、SubSub 中的“this.YYY”内部访问形式:在此种方式形式下,不管是否重写或重新定义过父类Base中protected方法与属性,子类Sub、SubSub一定可以访问的。

b.在Sub、SubSub 中“Base x = new XXX (); x.YYY;”外部访问形式:此种形式就不一定的能访问的到了,这要看父类Base与子类Sub、SubSub是否在同一包(注意,此时与是否重写或重新定义过这些protedted方法与属性没有关系);

c.在SubSub 中“Sub x = new XXX (); x.YYY;” 外部访问形式:此种访问形式能否访问关键看Sub是否重写或重新定义过Base的属性与方法: i. 如果重写或重新定义过,则看Sub与SubSub是否在同包中 ii.如果没有,则看Base与SubSub是否在同包中

3.在其他类Other中:此时只支持外部访问形式,不过到底是要求Other与Base同包还是要求Other与Sub同包,则要依你访问方式而定了:

a. 如果是通过父类引用“Base x = new XXX (); x.YYY;”形式来访问的,则要

求Other与Base同包;

b. 如果是通过子类引用“Sub x = new Sub (); x.YYY;”形式来访问的,情况又会比较复杂了,此时关键是看子类Sub是否重写或重新定义过父类Base中的protected方法与属性:

i.如果重写或重新定义过了,则要求Other与Sub同包即可; ii.如果没有重写或重新定义过了,则要求Other与Base同包即可; 另外,写到这里我想到了Object中的clone方法,为什么要求具有克隆能力的类要求实现Cloneable接口与clone方法呢:Object.clone()访问修饰符为protected,如果某个类没有重写此方法,则Object中的clone()方法除被自己与子类能调用方法外,其他不管与这个类在同一包还是不同包都是不可见的,因为未重写,还是属于Object中的方法,又Object在java.lang包中,与我们定义的包又不在java.lang包中,所以不能访问到(这也与你在在程序里定义了Object o = new Object();你还是不能在当前类中调用o.clone();一样),这也恰好符合上面 3.b.ii 这条规则。所以如果要能被不同包中的非子类克隆,则需重写Object.clone()并设置访问权限为public(如果重写后还是protected,则还是只能被同一包访问)。

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- 91gzw.com 版权所有 湘ICP备2023023988号-2

违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务