谈谈反射

2017/11/09 - Java

简介

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;简单说就是,只要给定类的名字,那么就可以通过反射机制来获得类的所有信息。

原理

Class文件由类装载器装载后,在JVM中将形成一份描述Class结构的元信息对象(Class反射对象),通过该元信息对象可以获知Class的结构信息。

Class反射对象:描述类语义结构,可以从Class对象中获取构造函数、成员变量、方法类等类元素的反射对象,并以编程的方式通过这些反射对象对目标类对象进行操作。

demo

一个简单的例子

public class Car {
    private String brand;
    private String color;
    private int maxSpeed;
    private String owner;//私有成员,没有对应的get和set方法;

    //①默认构造函数
    public Car(){}

    //②带参构造函数
    public Car(String brand,String color,int maxSpeed){
        this.brand = brand;
        this.color = color;
        this.maxSpeed = maxSpeed;
    }

    //③未带参的方法
    public void introduce() {
        System.out.println("brand:"+brand+"; color:"+color+"; maxSpeed:" +maxSpeed);
    }

    //私有方法
    private void whoHasIt(){
        System.out.println("The owner of this car is:" + this.owner );
    }

    //参数的getter/Setter方法
    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public int getMaxSpeed() {
        return maxSpeed;
    }

    public void setMaxSpeed(int maxSpeed) {
        this.maxSpeed = maxSpeed;
    }
}


public class ReflectCall {
    public static Car initByDefaultConst() throws Throwable {
        /**
         * ①通过类装载器获取Car类对象
         * 1.获取当前线程的ClassLoader
         * 2.通过指定的全限定类“reflect.Car”装载Car类对应的反射实例
         */
        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        Class class_car = loader.loadClass("reflect.Car");

        /**
         * ②获取类的默认构造器对象并通过它实例化Car
         * 1.通过Car的反射类对象获取Car的构造函数对象cons
         * 2.通过构造函数对象的newInstrance()方法实例化Car对象,其效果等同于new Car()
         */
        Constructor cons = class_car.getDeclaredConstructor((Class[])null);
        Car car = (Car)cons.newInstance();

        /**
         * ③获取类的成员变量(包含私有成员),并对成员变量赋值
         */
        Field ownerFld = class_car.getDeclaredField("owner");
        //取消Java语言访问检查以访问private变量
        ownerFld.setAccessible(true);
        ownerFld.set(car,"小明");


        /**
         * ④通过反射方法设置属性
         * 通过Car的反射类对象的getMethod(String methodName,Class paramClass)获取属性的Setter方法对象,
         * 第一个参数是目标Class的方法名;第二个参数是方法入参的对象类型。
         */
        Method setBrand = class_car.getMethod("setBrand",String.class);
        /**
         * 通过invoke(Object obj,Object param)方法调用目标类的方法,
         * 该方法的第一个参数是操作的目标类对象实例;第二个参数是目标方法的入参。
         */
        setBrand.invoke(car,"红旗CA72");

        Method setColor = class_car.getMethod("setColor", String.class);
        setColor.invoke(car, "黑色");
        Method setMaxSpeed = class_car.getMethod("setMaxSpeed",int.class);
        setMaxSpeed.invoke(car, 200);

        /**
         * ⑤获取类的私有方法,并调用它
         */
        Method whoHasItMtd = class_car.getDeclaredMethod("whoHasIt",(Class[])null);
        //取消Java语言访问检查以访问private方法
        whoHasItMtd.setAccessible(true);
        whoHasItMtd.invoke(car,(Object[])null);

        return car;
    }

    public static void main(String[] args) throws Throwable {
        Car car = initByDefaultConst();
        car.introduce();
    }
}

获取Class类的方法

Class<?> cl1 = ReflectMethod.class;
Class<?> cl2 = new ReflectMethod().getClass();
Class<?> cl3 = Class.forName("test.ReflectMethod");
Class<?> cl4 = cl2.getSuperclass();
Class<?> cl5 = Double.TYPE;

获取所有信息

package testReflect;  
import java.lang.reflect.*;    
public class PrintClassInfo {    

    private PrintClassInfo(){}    

    public static void printClassInfo(String name){    
        try{    
            Class cl = Class.forName(name);  
            String pack = cl.getPackage().getName();  
            System.out.println("package " + pack);  
            Class supercl = cl.getSuperclass();    
            String modifiers = Modifier.toString(cl.getModifiers());    

            if (modifiers.length() > 0) {  
                System.out.print(modifiers+" ");    
            }  

            System.out.print("class "+name);    
            if (supercl != null && supercl != Object.class) {  
                System.out.print(" extends " + supercl.getName());    
            }  

            Class []inters = cl.getInterfaces();  
            if (inters != null && inters.length > 0) {  
                System.out.print(" implements ");  
                for (int i=0; i<inters.length; ++i) {  
                    if (i!=0) {  
                        System.out.print(", ");  
                    }  

                    System.out.print(inters[i].getName());  
                }  
            }  

            System.out.print("\n{\nConstructors:\n");    
            printConstructors(cl);    

            System.out.println("Methods:");    
            printMethods(cl);    

            System.out.println("Fields:");    
            printFields(cl);    

            System.out.println("}");    
        } catch (ClassNotFoundException e){    
            e.printStackTrace();    
        }    

        System.exit(0);    
    }    

    public static void printConstructors(Class cl){    
        Constructor[] cons = cl.getConstructors();    
        for(Constructor c:cons){    
            String name = c.getName();    
            System.out.print("    ");    
            String modifiers = Modifier.toString(c.getModifiers());    
            if(modifiers.length() > 0) {  
                System.out.print(modifiers+" ");    
            }  

            System.out.print(name+"(");    

            Class[] paramTypes = c.getParameterTypes();    
            for(int i=0; i<paramTypes.length; i++) {    
                if(i>0)System.out.print(", ");    
                System.out.print(paramTypes[i].getName());    
            }    

            System.out.println(");");    
        }    
    }    

    public static void printMethods(Class cl){    
        Method[] methods = cl.getDeclaredMethods();    
        for(Method m:methods){    
            Class retType = m.getReturnType();    
            String name = m.getName();    
            System.out.print("    ");    
            String modifiers = Modifier.toString(m.getModifiers());    
            if(modifiers.length() > 0) {  
                System.out.print(modifiers + " ");    
            }  

            System.out.print(retType.getName() + " " + name + "(");    

            Class[] paramTypes = m.getParameterTypes();    
            for(int i=0; i<paramTypes.length; i++){    
                if(i>0) {  
                    System.out.print(", ");    
                }  

                System.out.print(paramTypes[i].getName());    
            }    

            System.out.println(");");    
        }    
    }    

    public static void printFields(Class cl){    
        Field[] fields = cl.getDeclaredFields();    
        for(Field f:fields){    
            Class type = f.getType();    
            String name = f.getName();    
            System.out.print("    ");    
            String modifiers = Modifier.toString(f.getModifiers());    
            if(modifiers.length()>0) {  
                System.out.print(modifiers + " ");    
            }  

            System.out.println(type.getName() + " " + name + ";");    
        }    
    }   
}

常见应用

  • Spring IOC机制
  • 动态代理

注意性能问题,请勿滥用反射


如果文章对您有帮助,欢迎扫描下方二维码赞助(一分也是爱噢),谢谢

Search

    一分也是爱噢 一分也是爱

    目录