Java反射调用与面向对象结合使用产生的惊艳

Posted 李新杰的博客园

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java反射调用与面向对象结合使用产生的惊艳相关的知识,希望对你有一定的参考价值。



缘起


我在看Spring的源码时,发现了一个隐藏的问题,就是父类方法(Method)在子类实例上的反射(Reflect)调用。

初次看到,感觉有些奇特,因为父类方法可能是抽象的或私有的,但我没有去怀疑什么,这可是Spring的源码,肯定不会有错。

不过我去做了测试,发现确实是正确的,那一瞬间竟然给我了一丝的惊艳。

这其实是面向对象(继承与重写,即多态)和反射结合的产物。下面先来看测试,最后再进行总结。

友情提示测试内容较多,不过还是值得一看。


具体方法的继承与重写


先准备一个父类,有三个方法,分别是public,protected,private。

public class Parent {

    public String m1() {
        return "Parent.m1";
    }

    protected String m2() {
        return "Parent.m2";
    }

    private String m3() {
        return "Parent.m3";
    }
}


再准备一个子类,继承上面的父类,也有三个相同的方法。

public class Child extends Parent {

    @Override
    public String m1() {
        return "Child.m1";
    }

    @Override
    protected String m2() {
        return "Child.m2";
    }

    private String m3() {
        return "Child.m3";
    }
}


public和protected是对父类方法的重写,private自然不能重写。

首先,通过反射获取父类和子类的方法m1,并输出:

Method pm1 = Parent.class.getDeclaredMethod("m1");
Method cm1 = Child.class.getDeclaredMethod("m1");

Log.log(pm1);
Log.log(cm1);


输出如下:

public java.lang.String org.cnt.java.reflect.method.Parent.m1()
public java.lang.String org.cnt.java.reflect.method.Child.m1()


可以看到,一个是父类的方法,一个是子类的方法。

其次,比较下这两个方法是否相同或相等:

Log.log("pm1 == cm1 -> {}", pm1 == cm1);
Log.log("pm1.equals(cm1) -> {}", pm1.equals(cm1));


输入如下:

pm1 == cm1 -> false
pm1.equals(cm1) -> false


它们既不相同也不相等,因为一个在父类里,一个在子类里,它们各有各的源码,互相独立。

然后,实例化父类和子类对象:

Parent p = new Parent();
Child c = new Child();


接着父类方法分别在父类子类对象上反射调用:

Log.log(pm1.invoke(p));
Log.log(pm1.invoke(c));


输出如下:

Parent.m1
Child.m1


父类方法在父类对象上反射调用输出Parent.m1,这很好理解。

父类方法在子类对象上反射调用输出Child.m1,初次看到的话,还是有一些新鲜的。

明明调用的是父类版本的Method,输出的却是子类重写版本的结果。

然后子类方法分别在父类子类对象上反射调用:

Log.log(cm1.invoke(p));
Log.log(cm1.invoke(c));


输出如下:

IllegalArgumentException
Child.m1


子类方法在父类对象上反射调用时报错

子类方法在子类对象上反射调用时输出Child.m1,这很好理解


按照同样的方式,对方法m2进行测试,得到的结果和m1一样。

它们一个是public的,一个是protected的,对于继承与重写来说是一样的。

然后再对方法m3进行测试,它是private的,看看会有什么不同。

首先,父类方法分别在父类和子类对象上反射调用:

java反射机制

java反射与注解结合使用(根据传入对象输出查询sql)

Java反射

Java反射

面向对象 - 总结

面向对象之反射及内置方法