访问修饰符的真正理解
Posted HNFXS985
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了访问修饰符的真正理解相关的知识,希望对你有一定的参考价值。
首先,必须明确Java中类成员的访问修饰符(public、private、protect、默认或friendly等,C++也同理),并不能简单的理解为书上说的如“子类可以访问”,具体因结合类的内存布局图来理解。例如一个父类有public a成员和protect b成员,在其子类的方法中访问a时,要考虑子类的内存布局能否看到a。 结合内存布局图就可以理解所谓“子类可以访问父类的protect b成员”说的是指本子类继承了父类的成员b,所以也具有b,当然就可以访问了。对于private成员,子类不继承,当然就没有了。 对于public的东西,在任何地方都能找到,对于private和protect就看通过内存布局能不能找到(即属于自己的可以找到,不属于自己的东西当然找不到了)。
【总之一句话,能不能访问,就看在当前作用域下能不能找到。】
以下是原因分析:
在Core Java中有这样一段话“在Object类中,clone方法被声明为protected,因此无法直接调用anObject.clone()。子类只能直接调用受保护的clone方法克隆它自己。为此,必须重新定义clone方法,并将它声明为public,这样才能让所有的方法克隆对象”。但是不是所有的子类都可以访问受保护的方法吗?不是每个子类都是Object的之类吗?下面就用例子来说明下protected访问修饰符的问题。
在package1中创建SuperClass.java文件,里面有一个protected方法,内容如下。
[java] view plain copy print ?
- package package1;
- public class SuperClass
- protected void method()
- System.out.println("This is a protected method in the super class .");
[java] view plain copy print ?
- package package1;
- public class SubClass1 extends SuperClass
- public static void main(String[] args)
- SuperClass sup = new SuperClass();
- SubClass1 sub1 = new SubClass1();
- SubClass2 sub2 = new SubClass2();
- sup.method(); //Compile OK
- sub1.method(); //Compile OK
- sub2.method(); //Compile OK
- class SubClass2 extends SuperClass
如果在另一个包package2中创建SubClass1.java文件,内容与包package1中的SubClass1.java内容相同。
[java] view plain copy print ?- package package2;
- import package1.SuperClass;
- public class SubClass1 extends SuperClass
- public static void main(String[] args)
- SubClass1 sub1 = new SubClass();
- SubClass2 sub2 = new SubClass2();
- Sub1.method(); //Compile OK
- sub2.method(); //Compile Error
- class SubClass2 extends SuperClass
如果我们在package2中的SubClass2中重写SuperClass的method方法。
[java] view plain copy print ?- package package2;
- import package1.SuperClass;
- public class SubClass extends SuperClass
- public static void main(String[] args)
- SubClass sub = new SubClass();
- SubClass2 sub2 = new SubClass2();
- sub.method(); //Compile OK
- sub2.method(); //Compile OK
- class SubClass2 extends SuperClass
- protected void method()
- super.method();
如果我们在一个类中调用父类对象的protected方法会怎么样?
在package1中创建父类SuperClass.java文件,里面有一个protected方法,内容如下。
[java] view plain copy print ?
- package package1;
- public class SuperClass
- protected void method()
- System.out.println("This is a protected method in the super class .");
在另一个包package中创建子类SubClass.java文件,内容如下。
[java] view plain copy print ?
- package package2;
- import package1.SuperClass;
- public class SubClass extends SuperClass
- public static void main(String[] args)
- SuperClass sup = new SuperClass();
- SubClass sub = new SubClass();
- sup.method(); //Compile Error
- sub.method(); //Compile OK
这里我在SubClass继承另一个包中的SuperClass,这个SuperClass中有一个protected方法method()。在SubClass类中调用SubClass类的实例sub的method()方法,编译不会报错。而同样调用SuperClass类的实例sup的method()方法,编译报错!
protected方法不是可以被子类访问的吗?
从接触Java开始就了解Java中访问修饰符的权限可以用下面这个表格概括:
作用域 | 当前类 | 同包 | 子孙类(不同包) | 其他 |
---|---|---|---|---|
public | Y | Y | Y | Y |
protected | Y | Y | Y | N |
default | Y | Y | N | N |
private | Y | N | N | N |
现在必须明确的是:类SubClass确实是继承了类SuperClass(包括它的method方法),所以在类SubClass中可以调用自己的method方法。但类SuperClass的protected方法对其不同包子类SubClass来说,是不可见的。
注意protected访问修饰符的规则及其微妙。
以上是关于访问修饰符的真正理解的主要内容,如果未能解决你的问题,请参考以下文章