zoukankan      html  css  js  c++  java
  • Java——反射机制


    反射概念:

    Java反射是Java被视为动态(或准动态)语言的一个关键性质。这个机制允许程序在运行时透过Reflection APIs取得任何一个已知名称的class的内部信息,包括其modifiers(诸如public, static 等)、superclass(例如Object)、实现之interfaces(例如Cloneable),也包括fields和methods的所有信息,并可于运行时改变fields内容或唤起methods。

    Java反射机制容许程序在运行时加载、探知、使用编译期间完全未知的classes。

    换言之,Java可以加载一个运行时才得知名称的class,获得其完整结构。

    反射是Java中一种强大的工具,能够使我们很方便的创建灵活的代码,这些代码可以再运行时装配,无需在组件之间进行源代码链接。但是反射使用不当会成本很高!


    JAVA反射机制提供了什么功能

    提供了如下功能:

    • 在运行时判断任意一个对象所属的类
    • 在运行时构造任意一个类的对象
    • 在运行时判段任意一个类所具有的成员变量和方法
    • 在运行时调用任一个对象的方法
    • 在运行时创建新类对象
    • 在使用Java的反射功能时,基本首先都要获取类的Class对象,再通过Class对象获取其他的对象。

    反射机制的作用:

    • 反编译:.class–>.java
    • 通过反射机制访问java对象的属性,方法,构造方法等;

    Java中JDK提供的Reflection API

    Java反射相关的API在包java.lang.reflect中。

    Member接口 该接口可以获取有关类成员(域或者方法)后者构造函数的信息。

    AccessibleObject类 该类是域(field)对象、方法(method)对象、构造函数(constructor)对象的基础类。它提供了将反射的对象标记为在使用时取消默认

    Java 语言访问控制检查的能力。 Array类 该类提供动态地生成和访问JAVA数组的方法。

    Constructor类 提供一个类的构造函数的信息以及访问类的构造函数的接口。 Field类 提供一个类的域的信息以及访问类的域的接口。

    Method类 提供一个类的方法的信息以及访问类的方法的接口。

    Modifier类 提供了 static方法和常量,对类和成员访问修饰符进行解码。

    Proxy类 提供动态地生成代理类和类实例的静态方法。


    动态创建代理类

    代理模式:代理模式的作用=为其他对象提供一种代理以控制对这个对象的访问。

    代理模式的角色:

    • 抽象角色:声明真实对象和代理对象的共同接口
    • 代理角色:代理角色内部包含有真实对象的引用,从而可以操作真实对象。
    • 真实角色:代理角色所代表的真实对象,是我们最终要引用的对象。

    动态代理:

    • java.lang.reflect.Proxy
      Proxy 提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类
    • InvocationHandler
      是代理实例的调用处理程序 实现的接口,每个代理实例都具有一个关联的调用处理程序。对代理实例调用方法时,将对方法调用进行编码并将其指派到它的调用处理程序的 invoke 方法。

    动态Proxy是这样的一种类:

    它是在运行生成的类,在生成时你必须提供一组Interface给它,然后该class就宣称它实现了这些interface。你可以把该class的实例当作这些interface中的任何一个来用。当然,这个Dynamic Proxy其实就是一个Proxy,它不会替你作实质性的工作,在生成它的实例时你必须提供一个handler,由它接管实际的工作。
    在使用动态代理类时,我们必须实现InvocationHandler接口


    实例练习:

    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.util.List;
    
    public class InvokeTest {
        /**
         * 利用反射机制实现调用方法
         * @param obj
         * @param methodName
         * @throws NoSuchMethodException
         * @throws SecurityException
         * @throws IllegalAccessException
         * @throws IllegalArgumentException
         * @throws InvocationTargetException
         */
        public static void test(String methodName) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
            InvokeTest test=new InvokeTest();
            //对象类型
            Class<?> cls=test.getClass();
            //利用反射机制获取该类型下的方法
            Method method=cls.getMethod(methodName, int.class,String.class);
            //执行该方法
            method.invoke(test, 10,"20");
    //      test.method(10,20)
        }
        /**
         * ...代表:一组相同类型的数据(不约束个数)
         * 一个方法里最多只能有一个...类型
         * ...类型必须出现在参数列表的最后位置
         * @param a
         */
        public static void e(int... a) {
            for(int i=0;i<a.length;i++) {
                System.out.println(a[i]);
            }
        }
    
        //反射机制
        //调用方法
        //不知道方法名或属性名
        //通过传递参数来实现调用
        public static void main(String[] args) {
            //...省略参数类型
            e(1,2,3,4,5);
    
            //反射机制
            try {
                test("d");
            } catch (NoSuchMethodException e) {
                // TODO Auto-generated catch block
                //没有该方法
                e.printStackTrace();
            } catch (SecurityException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    
        public void a() {
            System.out.println("aaaaaaaaaa");
        }
    
        public void b(int b) {
            System.out.println("b="+b);
        }
    
        public void c(int a,int b) {
            System.out.println("sum="+(a+b));
        }
    
        public void d(int a,String b) {
            System.out.println(a+b);
        }

    具体功能的实现

    反射机制获取类有三种方法,我们来获取Employee类型。

    //第一种方式:  
    Classc1 = Class.forName("Employee");  
    //第二种方式:  
    //java中每个类型都有class 属性.  
    Classc2 = Employee.class;  
    
    //第三种方式:  
    //java语言中任何一个java对象都有getClass 方法  
    Employeee = new Employee();  
    Classc3 = e.getClass(); //c3是运行时类 (e的运行时类是Employee)  

    创建对象:获取类以后我们来创建它的对象,利用newInstance:

    Class c =Class.forName("Employee");  
    
    //创建此Class 对象所表示的类的一个新实例  
    Objecto = c.newInstance(); //调用了Employee的无参数构造方法.  

    获取属性:分为所有的属性和指定的属性:
    a,先看获取所有的属性的写法:

    //获取整个类  
                Class c = Class.forName("java.lang.Integer");  
                  //获取所有的属性?  
                Field[] fs = c.getDeclaredFields();  
    
                       //定义可变长的字符串,用来存储属性  
                StringBuffer sb = new StringBuffer();  
                //通过追加的方法,将每个属性拼接到此字符串中  
                //最外边的public定义  
                sb.append(Modifier.toString(c.getModifiers()) + " class " + c.getSimpleName() +"{
    ");  
                //里边的每一个属性  
                for(Field field:fs){  
                    sb.append("	");//空格  
                    sb.append(Modifier.toString(field.getModifiers())+" ");//获得属性的修饰符,例如public,static等等  
                    sb.append(field.getType().getSimpleName() + " ");//属性的类型的名字  
                    sb.append(field.getName()+";
    ");//属性的名字+回车  
                }  
    
                sb.append("}");  
    
                System.out.println(sb);  

    b,获取特定的属性,对比着传统的方法来学习:

    public static void main(String[] args) throws Exception{  
    
    <span style="white-space:pre">  </span>//以前的方式:  
        /* 
        User u = new User(); 
        u.age = 12; //set 
        System.out.println(u.age); //get 
        */  
    
        //获取类  
        Class c = Class.forName("User");  
        //获取id属性  
        Field idF = c.getDeclaredField("id");  
        //实例化这个类赋给o  
        Object o = c.newInstance();  
        //打破封装  
        idF.setAccessible(true); //使用反射机制可以打破封装性,导致了java对象的属性不安全。  
        //给o对象的id属性赋值"110"  
        idF.set(o, "110"); //set  
        //get  
        System.out.println(idF.get(o));  
    }  

    参考博客:

    博客1:

    http://blog.csdn.net/liujiahan629629/article/details/18013523

    博客2:

    http://blog.csdn.net/yongjian1092/article/details/7364451

  • 相关阅读:
    mark
    ON DUPLICATE KEY UPDATE重复插入时更新
    lnmp上传文件
    websoket
    Nginx 和 Php 优化
    Nginx常见问题
    Keepalived 高可用
    https ; 及https证书
    Nginx动静分离;资源分离;rewrite重写、跳转、伪静态、规则、日志
    nginx负载均衡会话保持;四层负载均衡;端口转发
  • 原文地址:https://www.cnblogs.com/aixing/p/13327719.html
Copyright © 2011-2022 走看看