一、概述
在项目中,时常需要在项目中引用别人的库,最近笔者引用了一个库,但是该库有一些功能并不能满足笔者的需求。
因此我选择继承了这个类,并添加了一些其他的方法。
理论上这样做,也很符合Java
的面向对象的规范。
但不幸的是,运行过程中,竟然会抛出NoSuchMethodException
,这让笔者很是不解,在一番寻找之后,原来是这个库的类,里面定义了一些private
方法,并且用反射调用了这些private
方法。
由于我继承这个类,但是没法继承重写这个类的private
方法,所以,这个库的作者,通过反射调用我实现的子类,并不能找到private
的方法。
二、实践证明
下面笔者就通过一个简单的示例,证明这种弊端。
定义Father类
public class Father {
private void privateMethod(){
System.out.println("privateMethod====");
}
protected void protectedMethod(){
System.out.println("protectedMethod====");
}
public void publicMethod(){
System.out.println("publicMethod====");
}
}
定义Son类继承Father类
public class Son extends Father{
// 这里我只能重写protected或者是public方法
@Override
protected void protectedMethod() {
super.protectedMethod();
}
@Override
public void publicMethod() {
super.publicMethod();
}
}
调用示例
public class MyTest {
public static void main(String[] args) throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
Father father = new Father();
test(father); // 调用正常
Father father1 = new Son();
test(father1); // 调用失败, privateMethod会抛出NoSuchMethodException
}
private static void test(Father f) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
Class<? extends Father> aClass = f.getClass();
Father father = aClass.newInstance();
Method publicMethod = aClass.getDeclaredMethod("publicMethod");
publicMethod.invoke(father);
Method protectedMethod = aClass.getDeclaredMethod("protectedMethod");
protectedMethod.invoke(father);
Method privateMethod = aClass.getDeclaredMethod("privateMethod");
privateMethod.setAccessible(true);
privateMethod.invoke(father);
}
}
三、结语
综上所述,我们在实际开发过程中,应该避免通过反射去调用类的private
方法,这样会使得一个类失去了被其他人所继承的能力。违背了面向对象中,封装、继承、多态的三大特性。