Java基础——反射(Reflection)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/vae1314chuanchen/article/details/83550043

一、什么是反射

在运行状态中,对于任意一个类,都能够获取到这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性(包括私有的方法和属性),这种动态获取的信息以及动态调用对象的方法的功能就称为java语言的反射机制。通俗点讲,通过反射,该类对我们来说是完全透明的,想要获取任何东西都可以。

想要使用反射机制,就必须要先获取到该类的字节码文件对象(.class),通过字节码文件对象,就能够通过该类中的方法获取到我们想要的所有信息(方法,属性,类名,父类名,实现的所有接口等等),每一个类对应着一个字节码文件也就对应着一个Class类型的对象,也就是字节码文件对象。

获取字节码文件对象的三种方式;:

1、Class clazz1 = Class.forName(“全限定类名”);  
// 通过Class类中的静态方法forName,直接获取到一个类的字节码文件对象,此时该类还是源文件阶段,并没有变为字节码文件。
2、Class clazz2 = Person.class;    
// 当类被加载成.class文件时,此时Person类变成了.class,在获取该字节码文件对象,也就是获取自己, 该类处于字节码阶段。
3、Class clazz3 = p.getClass();    
// 通过类的实例获取该类的字节码文件对象,该类处于创建对象阶段

二、反射的使用

新建User类

使用user类进行测试

public class User {

    private int id;
    private int age;
    private String name;


    //javabean必须要有无参的构造方法!
    public User() {
    }

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

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getName() {
        return name;
    }

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

    public void setUname() {
        this.name = "cczhang";
    }
}

通过反射获取构造方法并使用

 String path = "com.cczhang.reflection.bean.User";
        try {
            Class<User> clazz = (Class<User>) Class.forName(path);
           
            //获得构造器信息
            Constructor[] constructors = clazz.getDeclaredConstructors();
            Constructor c1 = clazz.getDeclaredConstructor(int.class,int.class,String.class);
            System.out.println("获得构造器:"+c1);
            Constructor c2 = clazz.getDeclaredConstructor();
            System.out.println("获得构造器:"+c2);
            for(Constructor temp:constructors){
                System.out.println("构造器:"+temp);
            }

            //通过反射API调用构造方法,构造对象
            User u = clazz.newInstance();	//其实是调用了User的无参构造方法
            System.out.println(u);

            Constructor<User> c = clazz.getDeclaredConstructor(int.class,int.class,String.class);
            User u2 = c.newInstance(1001,18,"cczhang");
            System.out.println(u2.getName());
            System.out.println(u2.getAge());


        } catch (Exception e) {

        }

1.获取构造方法:
1).批量.获取构造方法的方法:
public Constructor[] getConstructors():所有"公有的"构造方法。
public Constructor[] getDeclaredConstructors():获取所有的构造方法(包括私有、受保护、默认、公有)。

2).获取单个的方法,并调用:
public Constructor getConstructor(Class… parameterTypes):获取单个的"公有的"构造方法。
public Constructor getDeclaredConstructor(Class… parameterTypes):获取"某个构造方法"可以是私有的,或受保护、默认、公有。

2、调用构造方法:
1)Constructor–>newInstance(Object… initargs)。

2)newInstance是 Constructor类的方法(管理构造函数的类)
api的解释为:
newInstance(Object… initargs)
使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。
它的返回值是T类型,所以newInstance是创建了一个构造方法的声明类的新实例对象。并为之调用。

获取成员变量并调用

            //获取属性信息
//			 Field[] fields = clazz.getFields(); //只能获得public的field
            Field[] fields = clazz.getDeclaredFields();//获得所有的field
            System.out.println(fields.length);
            for(Field temp:fields){
                System.out.println("属性:"+temp);
            }

            //通过反射API操作属性
            User user = clazz.newInstance();
            Field f = clazz.getDeclaredField("name");
            f.setAccessible(true); //这个属性不需要做安全检查了,可以直接访问
            f.set(user, "cczhang");		//通过反射直接写属性
            System.out.println(user.getName());	//通过反射直接读属性的值
            System.out.println(f.get(user));

注: f.set(user, “cczhang”);为User对象中的name属性赋值,即user.name = “cczhang”。第一个参数:要传入设置的对象,第二个参数:要传入实参。
暴力访问method.setAccessible(true);

获取成员方法并调用

		 //获取方法信息
            Method[] methods = clazz.getDeclaredMethods();

            for(Method m:methods){
                System.out.println("方法:"+m);
            }

            Method m01 = clazz.getDeclaredMethod("getName", null);
            //如果方法有参,则必须传递参数类型对应的class对象
            Method m02 = clazz.getDeclaredMethod("setName", String.class);

            //通过反射API调用普通方法
            User u3 = clazz.newInstance();
            Method method = clazz.getDeclaredMethod("setName", String.class);
            //需要两个参数,一个是要调用的对象(获取的反射),一个是实参
            method.invoke(u3, "cczhang");
            System.out.println(u3.getName());

通过反射获取泛型信息

public class Demo04 {
    public void test01(Map<String,User> map, List<User> list){
        System.out.println("Demo04.test01()");
    }
    public Map<Integer,User> test02(){
        System.out.println("Demo04.test02()");
        return null;
    }
    public static void main(String[] args) {
        try {
            //获得指定方法参数泛型信息
            Method m = Demo04.class.getMethod("test01", Map.class,List.class);
            Type[] t = m.getGenericParameterTypes();
            for (Type paramType : t) {
                System.out.println("#"+paramType);
                if(paramType instanceof ParameterizedType){
                    Type[] genericTypes = ((ParameterizedType) paramType).getActualTypeArguments();
                    for (Type genericType : genericTypes) {
                        System.out.println("泛型类型:"+genericType);
                    }
                }
            }
            //获得指定方法返回值泛型信息
            Method m2 = Demo04.class.getMethod("test02", null);
            Type returnType = m2.getGenericReturnType();
            if(returnType instanceof ParameterizedType){
                Type[] genericTypes = ((ParameterizedType) returnType).getActualTypeArguments();

                for (Type genericType : genericTypes) {
                    System.out.println("返回值,泛型类型:"+genericType);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

更多反射的用法请查阅JAVA的API文档。

相关连接

https://blog.csdn.net/wjzj000/article/details/54179894
https://blog.csdn.net/sinat_38259539/article/details/71799078

猜你喜欢

转载自blog.csdn.net/vae1314chuanchen/article/details/83550043