Java中子类是否会继承父类中的private成员
程序员文章站
2022-07-13 16:02:19
...
首先说明一下结果:不可以,至少Java语言规范上说的是不可以。
今天遇到一个问题:向上转型是安全的,不需要进行强制类型转换。原因当然是子类是父类的超集,所以父类中的东西(成员变量和成员方法在子类中都有)
/**
* @description : 测试继承 <br>
* @author Administrator <br>
*/
class SuperClass {
public void show() {
System.out.println("Super");
}
}
class SubClass extends SuperClass {
public void show() {
System.out.println("Sub");
}
}
public class TestSubsSuper {
public static void main(String[] args) {
SuperClass sup = new SubClass();
sup.show();
}
}
上面的结果输出是Sub。
仔细看上面的类,SubClass继承了SuperClass,并重写了其中的show()方法,其实你可以使用@Override加上注解。在看main()方法中,我们创建了一个SuperClass引用,但是我们用的是new SubClass(),也就是一个父类的引用实际上指向的是子类的对象。其实在使用new SubClass()之前,虚拟机并不知道这个sup引用指向的是父类还是SubClass子类或者是其他子类,而只有在运行的时候才能确定。这也就解释了如果使用sup调用了一个父类中不存在的方法,他会编译报错
提示父类中就没有定义这个方法。从这也可以看出在运行之前他调用的是父类中的show()方法。这里有个概念就是后期绑定(即子类可能覆盖了父类中的方法,那么最终执行的是子类中覆写的方法还是父类自己本身的方法在编译期是不确定的,而在运行期才能确定(注:这是和重载不同的地方,重载是在编译期就已经确定了要执行哪个版本的方法))。但是到底他会执行哪个方法呢?是子类的还是父类的呢?
应该从两点进行考虑:
一、这个引用指向的是子类还是父类;
二、如果指向的是子类,子类有没有覆写父类的方法。
如果是:SuperClass sup = new SuperClass(),即创建的是一个父类对象,那么无论子类是否覆写了父类的方法,调用的始终是父类的方法。
如果是:SuperClass sup = new SubClass(),即创建的是一个父类引用,但实际指向的是子类的对象。那么就要看子类是否覆写了父类中的方法,如果覆写了,那么肯定调用的是子类中的方法;而如果没有覆写,那么则会去调用父类中的方法。
但是为什么会有下面的这种写法呢?如果我想调用子类的方法,我直接创建一个子类的对象,如果我想调用父类的方法,就直接创建一个父类对象不就行了吗?答案当然是可以的。但是有时候这可能会导致一些很繁琐的事情 ,接着上面的例子说:
public class TestSubsSuper {
public static void differentShow(SuperClass sup) {
sup.show();
}
public static void main(String[] args) {
differentShow(new SuperClass());
differentShow(new SubClass());
}
}
我新增加了一个方法,这个方法接收一个SuperClass类型的引用作为参数,并使用它调用了show()方法。如果按照前面我们说的,调用哪个类的方法,就创建一个该类的对象,那么相应的我就应当创建很多个differentShow()方法,每一个方法接收一种类型的参数,很明显这样显得很冗余。但是有了上面的这种形式的写法,我使用一个父类类型的引用作为参数,同时我可以接收一个子类类型的对象,然后会根据前面所说的动态绑定在运行时确定执行哪个版本的方法,这样会很方便。其实,这也就是面向对象的一个重要特性——多态。
再回到我们最初的问题,那么这个子类继承父类,会继承他的private成员吗?
首先看下Java language specification中的说明:
A class C inherits from its direct superclass and direct superinterfaces all abstract and
non-abstract methods of the superclass and superinterfaces that are public, protected,
or declared with default access in the same package as C,
and are neither overridden (§8.4.8.1) nor hidden (§8.4.8.2) by a declaration in the class.
再看下Java 官方学习文档中的说明:
Private Members in a Superclass
A subclass does not inherit the private members of its parent class.
However, if the superclass has public or protected methods for accessing its private fields,
these can also be used by the subclass.
A nested class has access to all the private members of its enclosing class—both fields and methods. Therefore, a public or protected nested class inherited
by a subclass has indirect access to all of the private members of the superclass.
从上面我们可以看出其实子类继承父类的东西,不会继承其private成员。但是为什么不能继承private呢?
以下是个人理解:
首先我们知道,private类型的成员变量或者方法默认是final的,对于final方法,是不允许覆盖的。如果子类可以继承父类的private方法,那么自然而然可以覆写其中的方法,那也就与final冲突。
另外,对于private声明的成员在本类之外是不可以被访问的。但是如果子类继承了的话,那也就意味着可以访问父类的private,这和private又有冲突,所以其实是不会继承的。
但是,注意这一句话:However, if the superclass has public or protected methods for accessing its private fields,
these can also be used by the subclass.
class SuperClass {
private String str;
public void setStr() {
str = "Hello";
System.out.println(str);
}
public void show() {
System.out.println("Super");
}
}
public class TestSubsSuper {
public static void main(String[] args) {
SuperClass sup = new SubClass();
sup.setStr();
}
}
上面的那句话的意思如果父类中有public 或者 protected方法访问了父类中的private成员,那么子类也就可以通过这个方法间接访问父类的private成员。(也就是说父类的private成员在类外不是绝对不可访问的)
以上就是所有内容,如果有说的不对的地方,恳请批评指正,以免给他人造成错误的理解,不胜感激。