欢迎来到萧静默的博客

书山有路勤为径,学海无涯苦作舟。

JAVA-反射

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

要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象。

阅读API的Class类得知,Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的

下面直接进行演示。

首先建立2个类

Person类

package cn.bruce.reflect;

public class Person {
    public String name;
    public int age;
    private String address;

    public Person()
    {
    }

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

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

    public void eat() {
        System.out.println(name + "想吃大餐!");
    }

    private void eat(String name, int age) {
        System.out.println(name + "想吃大餐!" + "因为今年已经" + age + "岁了!");
    }
    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + ", address=" + address+ "]";
    }

}

Student类

package cn.bruce.reflect;

public class Student {
    public String name;
    public int age;
    private String address;

    public Student()
    {
    }

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

    private Student(String name, int age)
    {
        this.name = name;
        this.age = age;
    }

    public void study() {
        System.out.println(name + "想要好好学习!");
    }

    private void study(String name, int age) {
        System.out.println(name + "想要好好学习!" + "因为今年已经" + age + "岁了!");
    }
    @Override
    public String toString() {
        return "Student [name=" + name + ", age=" + age + ", address=" + address+ "]";
    }

}

通过反射获取构造、字段、方法

package cn.bruce.reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class Test {
    public static void main(String[] args) throws Exception {
        // Class c = Person.class;//这个是直接的
        // 1,获取到Class对象
        Class c = Class.forName("cn.bruce.reflect.Person");// 包名.类名
        Constructor[] con = c.getConstructors();// 出来公有构造器
        for (Constructor constructor : con)
        {
            System.out.println(constructor);
        }
        System.out.println("------------------------------------------");
        Constructor[] con1 = c.getDeclaredConstructors();// 出来所有构造器
        for (Constructor constructor : con1)
        {
            System.out.println(constructor);
        }
        System.out.println("------------------------------------------");
        Field[] field = c.getFields();// 出来公有字段
        for (Field f : field)
        {
            System.out.println(f);
        }
        System.out.println("------------------------------------------");
        Field[] field1 = c.getDeclaredFields();// 出来所有字段
        for (Field f : field1)
        {
            System.out.println(f);
        }
        System.out.println("------------------------------------------");
        Method[] m1 = c.getDeclaredMethods();// 出来所有方法
        for (Method m : m1)
        {
            System.out.println(m);
        }
        System.out.println("---------------------------");
        Method m2 = c.getMethod("eat", null);// 出来公有指定方法
        System.out.println(m2);
        System.out.println("---------------------------");
        Method m3 = c.getDeclaredMethod("eat", String.class, int.class);// 出来私有指定方法
        System.out.println(m3);
    }
}

反射并使用各种方法、泛型擦除、通过配置文件进行反射

package cn.bruce.reflect;

import java.io.FileReader;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Properties;

public class Test1 {
    public static void main(String[] args) throws Exception {
        // 1,获取到Class对象
        Class c = Class.forName("cn.bruce.reflect.Student");
        // 2,获取指定的构造方法
        // public Student()//空参
        // Constructor con = c.getConstructor(null);
        // public Student(String name, int age, String address)
        Constructor con = c.getConstructor(String.class, int.class, String.class);
        // 3,通过构造方法类中Constructor的方法,创建对象
        // Object obj = con.newInstance(null);//空参
        Object obj = con.newInstance("小明", 22, "哈尔滨");
        // 显示
        System.out.println(obj);
        // 4,获取私有构造方法
        Constructor con1 = c.getDeclaredConstructor(String.class, int.class);
        // 5,暴力反射
        con1.setAccessible(true);// 取消 Java 语言访问检查
        Object obj1 = con1.newInstance("小明", 22);
        System.out.println(obj1);
        // 6,获取指定的方法
        Method m1 = c.getMethod("study", null);// 公有无参方法
        Method m2 = c.getDeclaredMethod("study", String.class, int.class);// 私有
        // 7,执行找到的方法
        m1.invoke(obj);
        m2.setAccessible(true);// M2需要暴力反射
        Object obj_m2 = m2.invoke(obj1, "小米", 99);
        // 以下测试泛型擦除
        ArrayList<Integer> list = new ArrayList<Integer>();
        list.add(999);
        // list.add("小米");出错
        // 1、获取ArrayList的class对象
        Class c_arr = Class.forName("java.util.ArrayList");
        // 2、获取方法
        Method m_arr = c_arr.getMethod("add", Object.class);
        // 3、调用方法
        m_arr.invoke(list, "小米");
        m_arr.invoke(list, "小毛");
        System.out.println(list);
        // 以下演示配置文件实现反射功能
        /*
         * 调用哪种方法不知道,类也不清楚,通过配置文件实现 运行类名与方法名,以键值对的形式,写在文本中 运行哪个类,读取配置文件即可 实现步骤
         * 1、准备配置文件,键值对,IO流读取配置文件reader 2、文件中的键值对存储至集合Properties,集合保存键值对:类名及方法名
         * 3、反射指定的class文件对象,获取方法 运行方法
         */
        // IO流读取
        FileReader fr = new FileReader("config.properties");
        // 创建集合对象
        Properties p = new Properties();
        // 调用集合方法,传递流对象
        p.load(fr);
        fr.close();
        // 通过键获取值
        String classname = p.getProperty("classname");
        String method = p.getProperty("method");
        // 反射获取指定类的文件对象
        Class c_pro = Class.forName(classname);
        // 可以传一下name
//        Constructor con_pro = c_pro.getConstructor(String.class, int.class, String.class);
//        Object obj_pro = con_pro.newInstance("笑笑", 33, "杭州");// 创建对象
        Object obj_pro = c_pro.newInstance();
        Method m_pro = c_pro.getMethod(method, null);
        m_pro.invoke(obj_pro, null);
    }
}

 

 

 

 

 

posted @ 2020-10-15 10:42  萧静默  阅读(108)  评论(0编辑  收藏  举报