本文共 5116 字,大约阅读时间需要 17 分钟。
一:修饰变量和方法
注意:protected中的子孙类(不同包)可以是Y也可以是N(下面解释一下)
创建一个基类TestObject(注意包是cn.aa)
package cn.aa;//基类public class TestObject { protected void f() { System.out.println("基类的受保护方法f"); }}
创建一个子类Son(注意包是cn.test)
package cn.test;import cn.aa.TestObject;//子类Son,子类和基类TestObject不在同一包中public class Son extends TestObject {}
创建一个测试类Testone(注意包是cn.aa)
package cn.aa;import cn.test.Son;public class Testone { public static void main(String[] args) { new Son().f(); // 该代码正常执行,代码相当于下面两句// Son a=new Son();// a.f(); }}
成功运行,输出:基类的受保护方法f
创建另外一个测试类(包是cn.test)
package cn.test;public class Testtwo { public static void main(String[] args) { // 在子类的包中调用子类实例的f方法 new Son().f(); // 编译失败 }}
运行失败
结论:基类TestObject 的方法f的可见性是包cn.aa及其子类,所以testone可以testtwo不行
重要概念:protected的可见性在于两点:
- 基类的protected成员是包内可见的,并且对子类可见;
- 若子类与基类不在同一包中,那么在子类中,子类实例可以访问其从基类继承而来的protected方法,而不能访问基类实例的protected方法。
第一条我是能理解的,上面那个就是一个简单的例子,但是第二条我有点乱,特别是而不能访问基类实例的protected方法这句搞不懂。
在涉及下面的实例前百度了一些概念:
(1)基类就是父类,派生类就是子类
(2)Clone()在Object类里面是protected权限
(3)所有的类都是Object的子类,java.lang.Object为默认父类
在碰到涉及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) }}
f()方法从类Father1继承而来,其可见性是包p1及其子类Son1和Son11(其实Father1类也是可以调用方法f()的)
首先看(1)(3),而由于调用f()方法的类Test1所在的包也是p1,因此(1)(3)处编译通过。
其次看(2)(4),其中的clone()方法的可见性是java.lang包及其所有子类,对于语句"son1.clone();"和"son11.clone();",二者的clone()在类Son1、Son11中是可见的,在Son1或者Son11类里面创建实例都是可以访问clone()的,但在Test1类中创建Son1或者Son11就不能,因此(2)(4)处编译不通过,当然了,如果是在Test1中创建该类的实例也是能访问clone()方法。
实例二:
package p2;class MyObject2 { protected Object clone() throws CloneNotSupportedException{ //super可以调用父类的方法 return super.clone(); }}package p22;public class Test2 extends MyObject2 { public static void main(String args[]) { MyObject2 obj = new MyObject2(); obj.clone(); // Compile Error ----(1) Test2 tobj = new Test2(); tobj.clone(); // Complie OK ----(2) }}
对于(1)而言,clone()方法来自于类MyObject2本身,因此其可见性为包p2及MyObject2的子类,虽然Test2是MyObject2的子类,但在Test2中不能访问基类MyObject2的protected方法clone(),因此编译不通过;
对于(2)而言,由于在Test2中访问的是其本身实例的从基类MyObject2继承来的的clone(),因此编译通过。
注意实例三和实例四的区别
实例三:
package p3;class MyObject3 extends Test3 {}package p33;public class Test3 { public static void main(String args[]) { MyObject3 obj = new MyObject3(); obj.clone(); // Compile OK ------(1) }}
对于(1)而言,clone()方法来自于类Test3,因此其可见性为包p33及其子类MyObject3,而(1)正是在p33的类Test3中调用,属于同一包,编译通过。
实例四:
package p4;class MyObject4 extends Test4 { protected Object clone() throws CloneNotSupportedException { return super.clone(); }}package p44;public class Test4 { public static void main(String args[]) { MyObject4 obj = new MyObject4(); obj.clone(); // Compile Error -----(1) }}
对于(1)而言,clone()方法来自于类MyObject4,因此其可见性为包p4及其子类(此处没有子类),而类Test4却在包p44中,因此不满足可见性,编译不通过。
实例五:
package p5;class MyObject5 { protected Object clone() throws CloneNotSupportedException{ return super.clone(); }}public class Test5 { public static void main(String[] args) throws CloneNotSupportedException { MyObject5 obj = new MyObject5(); obj.clone(); // Compile OK ----(1) }}
对于(1)而言,clone()方法来自于类MyObject5,因此其可见性为包p5及其子类(此处没有子类),而类Test5也在包p5中,因此满足可见性,编译通过。
实例六:
package p6;class MyObject6 extends Test6{}public class Test6 { public static void main(String[] args) { MyObject6 obj = new MyObject6(); obj.clone(); // Compile OK -------(1) }}
对于(1)而言,clone()方法来自于类Test6,因此其可见性为包p6及其子类MyObject6,而类Test6也在包p6中,因此满足可见性,编译通过。
实例七:
package p7;class MyObject7 extends Test7 { public static void main(String[] args) { Test7 test = new Test7(); test.clone(); // Compile Error ----- (1) }}public class Test7 {}
对于(1)而言,clone()方法来自于类Object,因此该clone()方法可见性为包java.lang及其子类Test7,由于类MyObject7不在此范围内,因此不满足可见性,编译不通过。
子类能访问 protected 修饰符声明的方法和变量,这样就能保护不相关的类使用这些方法和变量。
下面的父类使用了 protected 访问修饰符,子类重写了父类的 openSpeaker() 方法。
class AudioPlayer { protected boolean openSpeaker(Speaker sp) { // 实现细节 }} class StreamingAudioPlayer extends AudioPlayer { protected boolean openSpeaker(Speaker sp) { // 实现细节 }}
如果把 openSpeaker() 方法声明为 private,那么除了 AudioPlayer 之外的类将不能访问该方法。
如果把 openSpeaker() 声明为 public,那么所有的类都能够访问该方法。
如果我们只想让该方法对其所在类的子类可见,则将该方法声明为 protected。
private修饰的变量:私有类变量(静态成员变量)。如果是public的类变量(static),那么可以通过类名去操作该类变量,同理,类方法也一样。访问限制修饰符按访问权限从高到低的排列顺序是public,protected,default,private。类和接口不能声明为 private。protected不能修饰类(内部类除外)
二:public类和友好类
class B {}
在另外一个类中使用友好类创建对象时,要保证他们在同一个包中。
public class B {}
转载地址:http://mjsh.baihongyu.com/