前言
在复习Java面向对象知识点的时候,有一个特征叫做继承。相信很多人都不陌生也能多多少少回答出来。
“子类继承了父类,可以获取父类的所有属性以及方法,但是子类无法访问父类中的private属性或方法”
真的是这样的吗?继续往下读吧!
正文
我们直接上测试代码,Test.java文件中的父亲拥有一件XXL的大衣以及一条XXL的秋裤,儿子可以直接获取父亲的物品。
class Father {
/**
* 父亲的大衣
*/
String coat = "XXL的大衣";
/**
* 父亲的秋裤
*/
String johns = "XXL的秋裤";
}
class Son extends Father {
/**
* 获取父亲的大衣
* @return String
*/
String getFatherCoat() {
return super.coat;
}
/**
* 获取父亲的秋裤
* @return String
*/
String getFatherJohns() {
return super.johns;
}
}
public class Test {
public static void main(String[] args) {
Son son = new Son();
System.out.println(son.getFatherCoat());
System.out.println(son.getFatherJohns());
}
}
运行上面的代码,打印结果如下:
XXL的大衣
XXL的秋裤
秋天来了,父亲想自己拥有秋裤,不想让儿子穿,他把秋裤设为私有的:
private String johns = "XXL的秋裤";
这时儿子就无法获取父亲的秋裤了!IDE报错了:
那儿子怎样才能得到父亲的秋裤呢?
通过创建public方法访问私有属性(方法)
或许很多人都能想到,就是父类提供一个public访问秋裤的方法,子类直接调用即可。我们在父类中增加一个方法,代码如下:
public String getJohns() {
return johns;
}
子类直接调用getJohns()方法即可,代码如下:
String getFatherJohns() {
return super.getJohns();
}
这时确实能够获取父亲的秋裤,但是需要父亲提供给我们一个方法才行,那可不可以直接获取呢?
通过将其定义为内部类,直接获取私有属性(方法)
我们新建一个Test1.java文件,并将父子类添加到Test1中,变成内部类,代码如下:
public class Test1 {
class Father {
/**
* 父亲的大衣
*/
String coat = "XXL的大衣";
/**
* 父亲的私人秋裤
*/
private String johns = "XXL的秋裤";
}
class Son extends Father {
/**
* 获取父亲的大衣
* @return int
*/
String getFatherCoat() {
return super.coat;
}
/**
* 获取父亲的秋裤
* @return String
*/
String getFatherJohns() {
return super.johns;
}
}
public static void main(String[] args) {
// 由于Son是内部类,不能直接通过new Son()来获取实例
Son son = new Test1().new Son();
System.out.println(son.getFatherJohns());
}
}
在IDE中竟然没有报错,我们运行一下看看,竟然成功获取了父亲的私人秋裤!
既然内部类可以直接获取父类的私有属性,那能不能直接调用父类的私有方法呢?
我们在父类中添加一个私有方法获取他本人的秋裤,代码如下:
private String getJohns() {
return johns;
}
儿子直接调用父类的getJohns(),代码如下:
String getFatherJohns() {
return super.getJohns();
}
IDE也没有把报错,运行一下代码,确实成功获取到了!
那不通过子类,而是直接通过父类的实例,也能获取到父类的私有属性吗?
我们再次尝试一下,直接在main方法中添加如下代码:
System.out.println(new Test1().new Father().johns);
发现IDE确实没报错,而且也可以成功运行并打印出父亲的秋裤。
当然,直接调用父亲的私有方法也是可以的,我们继续在main方法中添加如下代码:
System.out.println(new Test1().new Father().getJohns());
打印结果如下:
那还有没有其他方式可以直接访问父类的私人秋裤呢?
获取有小伙伴想到了(没有想到的话也配合我一下,假装各位都想到了?),没错就是通过反射!
通过反射获取父类的所有属性(方法)
我们回到Test.java中,在main方法中添加如下代码:
Father father = new Father();
// 获取父亲的类
Class clazz = father.getClass();
// 获取父亲的所有属性
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
// 设置允许访问私有变量
field.setAccessible(true);
try {
// 打印父亲的属性信息
System.out.println("通过反射获得的 " + field.get(father));
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
运行代码,打印结果,可以看到成功打印出父亲的所有属性值,当然包括私有属性:
总结
通过以上测试,我们可以得出:除了定义一个public方法获取私有属性之外,还可以通过下面两种方式直接获取私有属性(方法):
- 通过将其定义为内部类,直接访问private修饰的属性(方法)
- 通过反射,并设置允许访问私有属性
field.setAccessible(true);
好了,文章到这里也就结束了,南方最近天气转凉,各位小伙伴记得穿秋裤!