带你搞懂Java反射

2019-12-30  本文已影响0人  爺珍爱那颗心

什么是反射

运行时才知道要操作的类是什么,并且可以在运行时获取类的完整构造,并调用对应方法

反射的缺点

因为反射是运行时动态的去创建类的对象,所以运行效率上必然比直接创建对象要慢。

为什么使用反射

当我们不知道要初始化的类对象是什么但又需要创建类对象时候。

使用场景

1.突破私有权限修饰符的约束限制。(须小心使用
2.写框架代码的时候经常需要用。
3.阅读源码。

如何使用反射

public class Demo {
    String str;
    private int number;

    public Demo() {
    }

    public Demo(String str, int number) {
        this.str = str;
        this.number = number;
    }

    public String getStr() {
        return str;
    }

    public void setStr(String str) {
        this.str = str;
        System.out.println("str");
    }

    public int getNumber() {
        return number;
    }

    public void setNumber(int number) {
        this.number = number;
        System.out.println("number");
    }
    
    private void priMethod(){
        System.out.println("priMethod");
    }
}

①获取Class对象

Demo demo = new Demo();
 //1
Class test = Demo.class
//2
Class test = demo.getClass();
//3
Class test = Class.forName("全限定名");   

//全限定名指包名+类名,通常我们都采用方式三进行反射。

②获取类的实例

Demo demo = (Demo) test.newInstance();

③获取构造方法

Class<Demo>clazz = (Class<Demo>)Class.forName("包名+Demo");
//获取全部Constructor对象
Constructor<Demo> [] constructors = (Constructor<Demo> 
[])clazz.getConstructor();
//获取带参数的构造方法
Constructor<Demo> constructor = clazz.getConstructor(String.class,int.class);

注意:获取带参数的构造方法时不需要进行转型
通过有参数的构造拿到对象实例

Demo demo = constructor.newInstance("Demo",1);

④获取方法

获取clazz对应类中的所有方法包括从父类继承来的所有方法,但不能获取private修饰的方法

//获取clazz对应类中的所有方法,包括从父类继承来的所有方法,但不能获取private方法
Method [] methods = clazz.getMethods();

如果只获取当前类的方法,并包含私有方法,则使用getDeclareMethods即可。

Method [] methods = clazz.getDeclareMethods();

如果只获取指定方法,若方法有参数需要参数名称和参数列表无参就不需要写了。
注意:与获取构造方法一样,带参方法也不需要转型

Method methodStr = clazz.getDeclaredMethod("setStr",String.class);
Method methodInt = clazz.getDeclaredMethod("setNumber",int.class);

⑤获取变量

获取clazz对应类中的所有变量包括父类的变量,但不能获取private修饰的变量

//获取clazz对应类中的所有变量,包括父类的所有变量,但不能获取private变量
Field [] fields = clazz.getFields();

如果只获取当前类的变量,并包含私有变量,则使用getDeclaredFields即可。

Field [] fields = clazz.getDeclaredFields();

如果只获取指定变量,需要传入变量的名字

Field fieldStr = clazz.getDeclaredField("str");

⑥获取并执行方法

非私有方法调用时采用method.invoke(类的实例)方法,传入②或③步拿到的类的实例,和方法需要的参数即可。

methodInt.invoke(demo,1);

私有方法调用时,须在method.invoke(类的实例)方法,调用method.setAccessible(true);方法。

Method methodPriMethod = clazz.getDeclaredMethod("priMethod");
methodPriMethod.setAccessible(true);
methodPriMethod.invoke(demo);

⑦获取变量的值并设置值

注意:与私有方法一样,若想获取私有变量的值,需先写field.setAccessible(true);方法。

Demo demo = new Demo("str",1);
fieldStr.get(demo);
fieldStr.set(demo,"test");

到这里反射的全部用法和概念就记录完成了,这个系列会持续进行更新,如果你觉得对你有帮助,不想错过更新,可以点赞关注。

最后送一句话给自己也与各位共勉

行百里者半九十,不要轻易自满,永远记得坚持超越自己,加油!!!

上一篇 下一篇

猜你喜欢

热点阅读