Spring基础之 反射(Reflection)

Posted inspire0x001

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring基础之 反射(Reflection)相关的知识,希望对你有一定的参考价值。

1.了解Class

package com.inspire.reflection.Class_api;

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

public class ClassUtils {
    public static void main(String[] args) {
        String s="abc";
        printclassFieldMessage(s);
        printClassMethodMessage(s);
    }
    /**
     * 打印类的信息,成员方法
     * @param obj  该对象所属类的信息
     */
    public static void printClassMethodMessage(Object obj){
        //获取类的信息,获取类的类类型
        Class c1=obj.getClass();//传递的哪个子类的对象,c就是该子类的类类型
        //获取类的名称
        System.out.println("类名是:"+c1.getName());
        //获取方法
        /*
        Method类,方法的对象
        一个成员方法就是一个Method对象
        getMethods方法获取的是所有的public的方法,包括父类继承而来的
        getDeclaredMethods方法获取的是所有该类自己定义的方法。不问访问权限
         */
        Method[] methods=c1.getMethods();
//        Method[] method=c1.getDeclaredMethods();
        for (int i = 0; i <methods.length ; i++) {
            //获取方法的返回值类型的类类型(比如返回String类型,返回的是String.class)
            Class returnType=methods[i].getReturnType();
            System.out.print(returnType.getName()+" ");

            //获取方法的名称
            System.out.print(methods[i].getName()+"(");

            //获取参数类型   获取的是参数列表类型的类类型
            Class[] paramType=methods[i].getParameterTypes();

            for (Class c:paramType) {
                System.out.print(c.getName()+",");
            }
            System.out.println(")");
        }
    }
    /**
     * 打印类的信息,成员变量
     * @param obj
     */
    public static void printclassFieldMessage(Object obj) {
        //获取成员变量
        /**
         * 成员变量也是对象
         * java.lang.reflect.Field
         * Field封装了关于成员变量的操作
         * getFields方法获取的是所有的public的成员变量信息
         * getDeclaredFields()获取的是该类自己声明的成员信息(public/private)
         */
        Class c1=obj.getClass();//传递的哪个子类的对象,c就是该子类的类类型
        //Field[] fields=c1.getFields();
        Field[] fields=c1.getDeclaredFields();
        for (Field f:fields) {
            //得到成员变量类型的类类型
            Class fieldType=f.getType();
            //得到成员变量的名称
            String typeName=f.getName();
            System.out.println(typeName+" "+fieldType);
        }
    }
    /**
     * 打印对象的构造函数的信息
     * @param obj
     */
    public static void printClassConMessage(Object obj){
        Class c=obj.getClass();
        /*
        构造函数也是对象
        java.lang.Constructor中封装了构造函数的信息
        getDeclaredConstructor获取自己声明的构造函数
         */
        Constructor[] constructors=c.getDeclaredConstructors();
        //Constructor[] constructors=c.getConstructors();
        for (Constructor constructor:constructors) {
            System.out.println(constructor.getName()+"(");
            //获取构造函数的参数列表
            Class[] paramType=constructor.getParameterTypes();
            for (Class c1:paramType) {
                System.out.print(c1.getName()+",");
            }
            System.out.println(")");
        }
    }
}

2.获取一个类的类对象

(1).定义一个类

public class Student {
    private int id;
    private String name;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    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;
    }

    private int age;

}

(2).获取类对象

public class ClassDemo1 {
    public static void main(String[] args) {
        //Student的实例对象如何表示?
       // Student student=new Student();
        /*Student也是实例对象,是Class类的实例对象。如何表示?
        任何一个类都是Class类的实例对象,都有三种表示方法
        */
        //方式一:任何一个类都有一个隐含的静态成员class
        Class c1=Student.class;
        //方式二:已知该类的对象,通过getClass方法
        Student student=new Student();
        Class c2=student.getClass();
        /*
         c1,c2表示了Student类的类类型(Class type)
         万事万物皆对象
         类也是对象,是Class类的实例对象
         这个对象我们称为该类的类类型
          */
        //c1,c2都代表了Student类的类类型,一个类只可能是Class类的一个实例对象
        System.out.println(c1==c2);  //true
        //方式三:
        try {
            Class c3=Class.forName("com.inspire.reflection.Class_object.Student");
            System.out.println(c2==c3);  //true
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        /*
        有了类的类类型,我们可以通过类类型创建该类的对象.即通过c1,c2,c3创建对象
         */
        try {
            Student student1= (Student) c1.newInstance();
            //调用方法
            student1.getAge();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}

3.通过反射调用方法

public class Printer {

    public void printA(){
        System.out.println("无参的方法..........");
    }
    public void printA(int a,int b){
        System.out.println(a+":"+b);
    }

}
public class MethodDemo {
    public static void main(String[] args) {
        Printer printer=new Printer();
        Class c=printer.getClass();
        try {
            //获取方法
            Method method= c.getDeclaredMethod("printA", int.class, int.class);//获取自己声明的方法
            //c.getMethod("printA", int.class, int.class);//获取public的方法
            //方法的反射操作
            method.invoke(printer,1,3); //放回方法的返回值
            System.out.println("=========================");
            Method method1=c.getDeclaredMethod("printA");
            method1.invoke(printer);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

4.通过反射理解泛型

java中泛型是防止错误输入的。只在编译时有效。编译之后集合的泛型是去泛型化的
public static void main(String[] args){
        ArrayList<String> list1=new ArrayList<String>();
        list1.add("hello");
     ArrayList list2=new ArrayList<String>();
     //System.out.println(c1==c2);//结果为true,说明编译之后集合的泛型是去泛型化的
        Class c2=list1.getClass();
        try {
            Method method=c2.getMethod("add", Object.class);
        //注意这里:虽然上面定义list1时是String类型的,但是这里可以加入int类型的数据
            method.invoke(list1,100);
            System.out.println(list1.size());
            System.out.println(list1);//不能用foreach遍历,类型不一样了
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

 


以上是关于Spring基础之 反射(Reflection)的主要内容,如果未能解决你的问题,请参考以下文章

Java进阶之reflection(反射机制)——反射概念与基础

Java进阶之reflection(反射机制)——反射概念与基础

Qt基础之二十三:反射(Reflection)

Qt基础之二十三:反射(Reflection)

Go语言之reflection

Golang基础_10-反射reflection