开发者社区 > 博文 > Java反射学习
分享
  • 打开微信扫码分享

  • 点击前往QQ分享

  • 点击前往微博分享

  • 点击复制链接

Java反射学习

  • 京东城市JUST团队
  • 2021-01-27
  • IP归属:未知
  • 23160浏览

你对反射的理解

  1. 应用在一些通用性较高的代码中
  2. 框架的底层基于反射
  3. 在框架开发中,都是基于配置文件开发,在配置文件中配置子类,可以通过反射得到类中的所有内容,可以让类中的某个方法执行
  4. 类中的所有内容:属性、没有参数的构造方法、有参数的构造方法、普通方法,都可以通过反射机制动态获得。

提出问题

那么接下来就看看怎么通过反射来获得类中的内容,首先了解一个类的加载过程:
1.编写类的源码,保存到硬盘;
2.编译成class文件;
3.把class文件加载到内存通过JVM执行。

所以,只要得到了这个class,我们就可以得到这个类的所有内容。

准备工作

首先,我们建立一个Person类,有name和age两个属性,有参数和无参数的构造函数还有封装属性的基本方法:

package jimo.reflect;

public class Person {
    //属性
    private String name;
    private int age;

    //无参和有参构造函数
    public Person(){
    }

    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }

    //普通方法
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

首先,了解通过反射获得类有三种方式:
方式1:类名.class
方式2:对象.getClass()
方式3:Class.forName(“路径”)

用代码看起来就是这样:

public static void main(String[] args) throws ClassNotFoundException {
        Class c1 = Person.class;
        Class c2 = new Person().getClass();
        Class c3 = Class.forName("jimo.reflect.Person");
    }

注意:路径包括包名,copy小技巧:在类名上右键:

1

实现代码

现在可以来获得类的属性,构造方法,普通方法了。

1 . 用反射获取对象实例,不用new:

public void getInstance() throws ClassNotFoundException, InstantiationException, IllegalAccessException{
        Class c = Class.forName("jimo.reflect.Person");
        Person p = (Person) c.newInstance();
    }

2 . 用反射获取类的属性:

public void getField() throws ClassNotFoundException, NoSuchFieldException, SecurityException, InstantiationException, IllegalAccessException{
        Class c = Class.forName("jimo.reflect.Person");
        Person p = (Person) c.newInstance();
        Field f = c.getDeclaredField("age");//参数为属性名称
        f.setAccessible(true);//设置可以访问私有属性
        try {
            f.set(p,20);//第一个参数为Person对象,第二个参数为设置的属性的值
            System.out.println(f.get(p));
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

3 . 通过反射操作有参构造函数:
为什么是有参呢?因为无参已经做过了。

public void testConstruct() throws Exception{
        Class c = Class.forName("jimo.reflect.Person");
        Constructor cs = c.getConstructor(String.class,int.class);//注意这个可变参数
        Person p = (Person) cs.newInstance("jimo",20);
        p.setAge(10);
        System.out.println(p.getAge());//结果10
    }

4 . 反射操作普通方法:

public void testMethod() throws Exception{
        Class c = Class.forName("jimo.reflect.Person");
        Person p = (Person) c.newInstance();
        Method md = c.getDeclaredMethod("setName", String.class);//第一个参数为方法名称,第二个是可变参数,为方法的参数类
        //md.setAccessible(true);
        md.invoke(p, "jimo");
        Method md2 = c.getDeclaredMethod("getName");
        System.out.println(md2.invoke(p));//结果为jimo
    }

那如果普通方法是静态的怎么做呢?很简单,因为静态方法直接由类调用,不通过实例,所以invoke第一个参数填 null 就好。

可以看到:
1. .setAccessible(true);这个方法可以使私有属性和方法被访问,相当于失去了封装的效果。
2. 我们很少用到反射来获取实例,着重理解反射的原理。

共0条评论