java中的反射

  • 反射是什么?

JAVA反射机制是在运行状态中,对于任意一个类,都能知道这个类的所有属性和方法。对于任意一个对象,都能调用它的任意一个方法和属性。这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

想要解剖一个类,必须先要获得该类的字节码对象。

 

  • 三种方式获得字节码对象

(1.创建对象阶段)Object类的getClass()方法

示例:Person p = new Person();

      Class clazz = p.getClass()

(2.源文件阶段)Class类的静态方法

示例:class.forName("类名")

      Class clazz = class.forName("com.pr.Person")

(3.字节码阶段)Class clazz = Person.class

 

  • 字节码对象的newInstance()方法通过无参构造函数创建对象

public class Demo {
    public static void main(String[] args) throws Exception {
        Class clazz = Class.forName("com.pr2.Person");     // 获取字节码对象
        Person p = (Person) clazz.newInstance();           // 通过无参构造方法创建对象
        p.eat();
    }
}

class Person{
    public Person() {};
    public void eat(){
        System.out.println("吃饭");
    }
}

 

  • 字节码对象通过有参构造函数创建对象

public class demo {
    public static void main(String[] args) throws Exception {
        Class clazz = Class.forName("com.pr3.Person");
        Constructor c = clazz.getConstructor(String.class,int.class);    // 发射阶段,都是操作字节码对象的
        Person p = (Person) c.newInstance("张三",13);
        System.out.println(p);
    }
}

class Person{
    private String name;
    private int age;

//    public Person() {}       无参构造注释掉

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

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

 

  • 字节码对象获取、修改私有成员变量

public class Demo {
    public static void main(String[] args) throws Exception {
        Person p = new Person("张三",13);
        System.out.println(p);
        Class clazz = p.getClass();
        Field f = clazz.getDeclaredField("name");     // 暴力反射获取字段
        f.setAccessible(true);                             // 去除私有权限
        f.set(p,"李四");
        System.out.println(p);
    }
}

class Person{
    private String name;
    private int age;

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

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

 

  • 字节码对象获取无参方法并使用

public class Demo {
    public static void main(String[] args) throws Exception {
        My m = new My();
        Class clazz = m.getClass();
        Method method = clazz.getMethod("eat");
        method.invoke(m);
    }
}

class My{
    public void eat(){
        System.out.println("我今天吃了一顿KFC");
    }
}

 

  • 字节码对象获取有参方法并使用

public class Demo {
    public static void main(String[] args) throws Exception {
        My m = new My();
        Class clazz = m.getClass();
        Method method = clazz.getMethod("eat",int.class);
        method.invoke(m,3);
    }
}

class My{
    public void eat(int num){
        System.out.println("我今天吃了" + num + "顿KFC");
    }
}

 

  • 利用上面的例子(字节码对象获取有参方法并使用)可以实现用反射越过泛型检查

public class Demo {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        ArrayList<Integer> list = new ArrayList<>();
        list.add(100);
        list.add(200);
        Class clazz = Class.forName("java.util.ArrayList");
        Method m = clazz.getMethod("add", Object.class);
        m.invoke(list,"哈哈哈");
        System.out.println(list);
    }
}
posted @ 2019-01-21 17:07  苦瓜爆炒牛肉  阅读(166)  评论(0编辑  收藏  举报