前言
JavaGuide中关于继承如下 3 点请记住:
- 子类拥有父类对象所有的属性和方法(包括私有属性和私有方法),但是父类中的私有属性和方法子类是无法访问,只是拥有。
尝试验证这一观点。
对象初始化
首先从对象初始化开始思考,一般继承某个父类的子类对象初始化时是按照以下顺序:
- 父类的静态变量和常量以及父类的静态代码块
- 子类的静态变量和常量以及子类的静态代码块
- 父类的变量赋默认值和父类代码块
- 父类的构造方法
- 子类的变量赋默认值和父类代码块
- 子类的构造方法
既然按照对象初始化顺序来说,子类的构造方法被调用的时候必然有一个父类对象被构造,那么必然有办法在子类构造时对父类的变量进行赋值。
Java如果不指定构造方法,会默认给每个类提供一个无参构造方法,那如果我的父类只有有参构造方法又会如何呢?
使用有参构造方法
首先准备好了父类,这个父类里面只有一个parentName
的属性,同时制定一个有参构造方法,代码如下:
public class Parent {
private String parentName;
public Parent(String parentName) {
this.parentName = parentName;
}
}
然后准备了子类继承父类,这个时候有意思的事情发生了,子类必须提供一个带参的构造方法来构造父类对象,同时要在这个带参构造方法里面通过super关键字调用父类的构造方法,否则编译会失败,最终代码如下:
public class Child extends Parent {
public Child(String parentName) {
super(parentName);
}
}
其实从这里就可以知道子类是拥有父类的私有属性的了,只是因为访问控制限制无法直接访问这个属性。
但是除了这个方法以外,我还有什么办法去佐证这个观点呢?当然有啦,而且还不止一种呢,我知道的就有两个办法:
- 直接查看字节码
- 使用反射获取
下面展示如何使用反射获取父类的属性的示例代码:
Child child = new Child("David");
try {
// 获取父类Class对象
Class parentClass = child.getClass().getSuperclass();
// 获取父类的属性
Field field = parentClass.getDeclaredField("parentName");
// 解除访问限制
field.setAccessible(true);
// 输出
System.out.println(field.get(child));
} catch (NoSuchFieldException e) {
// 这里只是演示用,实际开发时需要将错误信息打印到日志文件
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
输出结果:
David
标签:构造方法,对象,子类,无法访问,parentName,父类,属性
From: https://www.cnblogs.com/worshipone/p/18154116