• 反射


    package reflect;
    
    
    public class Car {  
        public String brand;  
        private String color;  
        private int maxSpeed;  
          
         //①默认构造函数  
        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);  
        }
    
        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;
        }  
        
    }  
    package reflect;
    
    import java.lang.reflect.AccessibleObject;
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    import java.lang.reflect.Modifier;
    
    public class ReflectTest {
        
        /** 
         *验证所有的类都是Class类的实例对象 
         * @throws ClassNotFoundException  
         */  
        public static void verifyIns() throws ClassNotFoundException{  
            System.out.println("-----验证所有的类都是Class类的实例对象 -----");
            //定义两个类型都未知的Class , 设置初值为null, 看看如何给它们赋值成Person类  
            Class<?> class1 = null;  
            Class<?> class2 = null;  
              
            //写法1, 可能抛出 ClassNotFoundException [多用这个写法]  
            class1 = Class.forName("reflect.Car");  
            System.out.println("(写法1) 包名: " + class1.getPackage().getName() + ","   
                    + "完整类名: " + class1.getName());  
              
            //写法2  
    //        class2 = Car.class;  
    //        System.out.println("(写法2) 包名: " + class2.getPackage().getName() + ","   
    //                + "完整类名: " + class2.getName());  
        } 
    
        /**
         * 通过获取类的默认构造器创建实例
         * @throws Throwable
         */
        public static void initByDefaultConst() throws Throwable {
            System.out.println("-----通过获取类的默认构造器创建实例-----");
            //写法1
            //通过类加载器获取car对象
            ClassLoader loader = Thread.currentThread().getContextClassLoader();//获取当前线程的ClassLoader
            Class clazz = loader.loadClass("reflect.Car");//通过指定的全限定类“reflect.Car”装载Car类对应的反射实例
            
            //获取类的默认构造器对象并通过它实例化car
            Constructor  cons = clazz.getDeclaredConstructor((Class[]) null);//通过Car的反射类对象获取Car的构造函数对象cons
            Car car = (Car) cons.newInstance();//通过构造函数对象的newInstrance()方法实例化Car对象,其效果等同于new Car()
            System.out.println("包名:"+car.getClass().getPackage().getName()+",完整类名:"+car.getClass().getName());
            //通过反射方法设置属性
            Method  setBrand = clazz.getMethod("setBrand", String.class);//通过Car的反射类对象的getMethod(String methodName,Class paramClass)获取属性的Setter方法对象,第一个参数是目标Class的方法名;第二个参数是方法入参的对象类型
            setBrand.invoke(car, "红旗");//获取方法反射对象后,即可通过invoke(Object obj,Object param)方法调用目标类的方法,该方法的第一个参数是操作的目标类对象实例;第二个参数是目标方法的入参。
            Method  setColor = clazz.getMethod("setColor", String.class);
            setColor.invoke(car, "红色");
            Method setMaxSpeed = clazz.getMethod("setMaxSpeed", int.class);
            setMaxSpeed.invoke(car, 200);
            Method introduce = clazz.getMethod("introduce",null);
            introduce.invoke(car, null);
            
            //写法2
    //        Class clazz = Class.forName("reflect.Car");
    //        Car car = (Car)clazz.newInstance();
    //        System.out.println("包名:"+car.getClass().getPackage().getName()+",完整类名:"+car.getClass().getName());
        }
        /**
         * 通过获取类的指定构造器创建实例
         * @throws Throwable 
         */
        public static void  initBySpecifiedConst() throws Throwable {
            System.out.println("-----通过获取类的指定构造器创建实例-----");
            ClassLoader loader = Thread.currentThread().getContextClassLoader();//获取当前线程的ClassLoader
            Class clazz = loader.loadClass("reflect.Car");//通过指定的全限定类“reflect.Car”装载Car类对应的反射实例
            Constructor c = clazz.getConstructor(String.class,String.class,int.class);
            Car car = (Car) c.newInstance("Benz","黑色",100);
            Method introduce = clazz.getMethod("introduce",null);
            introduce.invoke(car, null);
        }
     
        /**
         *获取构造器列表并用其中一个创建实例
         * @throws Throwable 
         * @throws Exception 
         */
        public static void getAllConstsAndNewInstance() throws Throwable  {
            System.out.println("-----获取构造器列表并用其中一个创建实例-----");
            ClassLoader loader = Thread.currentThread().getContextClassLoader();
            Class clazz = loader.loadClass("reflect.Car");
            Constructor[] constructors = clazz.getConstructors();
            Car car0 = (Car)constructors[0].newInstance();
            System.out.println("包名:"+car0.getClass().getPackage().getName()+",完整类名:"+car0.getClass().getName());
            Object obj = (Car)constructors[1].newInstance("Benz","黑色",100);
            System.out.println("包名:"+obj.getClass().getPackage().getName()+",完整类名:"+obj.getClass().getName());
        }
        
        /**
         * 获取并操作成员变量
         * @throws Throwable
         */
        public static void getAndProcessField() throws Throwable{
            System.out.println("-----获取并操作成员变量-----");
            Class clazz = Class.forName("reflect.Car");
            Object obj = clazz.newInstance();
    //        Field[] fields = clazz.getFields();//getFields():获得某个类的所有的公共(public)的字段,包括父类中的字段
            Field[] fields = clazz.getDeclaredFields();//getDeclaredFields():获得某个类的所有声明的字段,即包括public、private和proteced,但是不包括父类的申明字段。
            for(Object o :fields){
                System.out.println(o);
            }
    //         AccessibleObject.setAccessible(fields, true); //对所有属性设置访问权限  当类中的成员变量为private时 必须设置此项
             Field fieldBrand = clazz.getField("brand");
             fieldBrand.setAccessible(true);
             fieldBrand.set(obj, "BWM");//对当前属性设置访问权限  当类中的成员变量为private时 必须设置此项
             System.out.println("修改属性之后得到属性变量的值:" + fieldBrand.get(obj));
             Field fieldColor = clazz.getDeclaredField("color");
             fieldColor.setAccessible(true);
             fieldColor.set(obj, "white");//对当前属性设置访问权限  当类中的成员变量为private时 必须设置此项
             System.out.println("修改属性之后得到属性变量的值:" + fieldColor.get(obj));
        }
        /**
         * 获取并操作成员方法
         * @throws Throwable
         */
        public static void getAndProcessMethods() throws Throwable{
            System.out.println("-----获取并操作成员方法-----");
            ClassLoader  loader = Thread.currentThread().getContextClassLoader();
            Class clazz = loader.loadClass("reflect.Car");
    //        Method[] methods = clazz.getMethods(); //getMethods()返回某个类的所有公用(public)方法包括其继承类的公用方法,当然也包括它所实现接口的方法。
            Method[] methods = clazz.getDeclaredMethods();//getDeclaredMethods()对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。当然也包括它所实现接口的方法。
            for(Method m :methods){
                System.out.println("方法:"+m);
                System.out.println("方法名:"+m.getName());
                System.out.println("方法返回类型:"+m.getReturnType());
                System.out.println("函数访问修饰符:" + Modifier.toString(m.getModifiers()));  
            }
            Method methodIntroduce = clazz.getMethod("introduce",null);
            methodIntroduce.invoke(clazz.newInstance(), null);
            
            //取得类实现的接口,因为接口类也属于Class 
             Class interfaces[] = clazz.getInterfaces();  
                for (int i = 0; i < interfaces.length; i++) {  
                    System.out.println("实现的接口类名: " + interfaces[i].getName() );  
                }  
        }
        
        /**得到类加载器信息
         * @throws Throwable
         */
        public static void getClassLoader() throws Throwable{
            System.out.println("-----得到类加载器信息-----");
            Class clazz = Class.forName("reflect.Car");
            String classLoaderName = clazz.getClassLoader().getClass().getName();
            System.out.println("classLoaderName:"+classLoaderName);
        }
        
        
        public static void main(String args[]) throws Throwable{
             verifyIns();
             initByDefaultConst();
             initBySpecifiedConst();
             getAllConstsAndNewInstance();
             getAndProcessField();
             getAndProcessMethods();
             getClassLoader();
        }
        
    }

    常用反射的一些地方

    https://www.cnblogs.com/ldh-better/p/7148975.html#_label2_1

    1.工厂模式:Factory类中用反射的话,添加了一个新的类之后,就不需要再修改工厂类Factory了
    2.数据库JDBC中通过Class.forName(Driver).来获得数据库连接驱动
    3.分析类文件:毕竟能得到类中的方法等等
    4.访问一些不能访问的变量或属性:破解别人代码

     如何优化反射?

    一. 善用API
    
    比如,尽量不要getMethods()后再遍历筛选,而直接用getMethod(methodName)来根据方法名获取方法
    
    二、缓存
    
    比如,需要多次动态创建一个类的实例的时候,有缓存的写法会比没有缓存要快很多:
    
    // 1. 没有缓存
    void createInstance(String className){
        return Class.forName(className).newInstance();
    }
    
    // 2. 缓存forName的结果
    void createInstance(String className){
        cachedClass = cache.get(className);
        if (cachedClass == null){
            cachedClass = Class.forName(className);
            cache.set(className, cachedClass);
        }
        return cachedClass.newInstance();
    }
    为什么?当然是因为forName太耗时了。 

  • 相关阅读:
    vector在堆上还是在栈上(等待自己慢慢领悟吧)
    函数指针遇到typedef
    回调函数的代码示例
    _T和_L的区别
    MFC打开文件夹对话框
    C++中的抽象类和接口类
    UML图中继承和实现的区别
    扩展点(ExtensionPoint)
    组播(又称多播)是个好东西
    C++代码实现组播及归纳的流程图
  • 原文地址:https://www.cnblogs.com/thiaoqueen/p/8047007.html
Copyright © 2020-2023  润新知