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

    一:何为反射机制

         JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

      二,反射机制的作用:

           1,反编译:.class-->.java

           2,通过反射机制访问java对象的属性,方法,构造方法等;

           这样好像更容易理解一些,下边我们具体看怎么实现这些功能。

    三,在这里先看一下sun为我们提供了那些反射机制中的类:

    java.lang.Class;                
    
    java.lang.reflect.Constructor; java.lang.reflect.Field;        
    
    java.lang.reflect.Method;
    
    java.lang.reflect.Modifier;

    学会了这个,理解Spring的话,就简单很多。

    1,反射机制获取类有三种方法,

    //例程1:获取方法
    //方法一:
    //获得类类型的两种方式 Class classType = Class.forName("com.sun.Role"); //返回class对象所对应的类或接口中,所声明的所有方法的数组(包括私有方法) System.out.println("classType="+classType.getSimpleName()); //类名 System.out.println("classType="+classType.getCanonicalName());//类的全名 //方法二: Class classType2 = com.sun.Role.class; System.out.println("classType2="+classType2.getSimpleName()); System.out.println("classType2="+classType2.getCanonicalName());

    这里说的还有一个方法,不过最后一个方法觉得有点傻

          //方法三:
    Class classType3 = new Role().getClass(); System.out.println("classType3="+classType3.getSimpleName()); System.out.println("classType3="+classType3.getCanonicalName());

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

        //例程2:创建对象
          Object obj = classType.newInstance();

     3,获取属性:分为所有的属性和指定的属性

        a,先看获取所有的属性的写法:

        //获取属性:分为所有的属性和指定的属性:
          Field[] fs = classType.getDeclaredFields();  
        //定义可变长的字符串,用来存储属性  
          StringBuffer sb = new StringBuffer();  
          
          sb.append(Modifier.toString(classType.getModifiers()) + " class " + classType.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.获得特定的属性,然后进行修改

    //获取age属性  
         Field age = classType.getDeclaredField("age"); 
         Field name = classType.getDeclaredField("name"); 
        //打破封装   
         age.setAccessible(true); //使用反射机制可以打破封装性,导致了java对象的属性不安全。  
         name.setAccessible(true);
         System.out.println("Role class age is = "+age.get(obj));  
         System.out.println("Role class age is = "+name.get(obj));  
         age.set(obj, "110"); //set  
         System.out.println("Role class age is = "+age.get(obj)); 

     4.获取方法的类型和返回值

        Method[] methods = classType.getDeclaredMethods();
        StringBuffer sb2 = new StringBuffer();
        //遍历输出所有方法声明
        for(Method method : methods)
         {
            sb2.append("	");//空格  
            sb2.append(Modifier.toString(method.getModifiers())+"  ");//获得方法的类型
            sb2.append(method.getReturnType().getSimpleName().toString()+"  ");//获得方法的返回类型
            sb2.append(method.getName()+"();
    ");//获取方法名
        }
        System.out.println(sb2);

    详情可以去见API,基本上可以通过反射机制,在知道一个类的名字后,反编译出该类文件为.java文件。

    5.通过反射机制调用方法

        // 通过反射调用方法
        //调用方法一:
        // 首先需要获得与该方法对应的Method对象
        Method toMyStringMethod = classType.getDeclaredMethod("toMyString",new Class[]{String.class});  
        toMyStringMethod.setAccessible(true);
        Object result2 = toMyStringMethod.invoke(obj, new Object[]{"sun"});//为该方法传入参数
        System.out.println(result2.toString());
        //调用方法二:
        Method toMyStringMethod1 = classType.getMethod("toMyString",new Class[]{String.class});  
        Object result = toMyStringMethod1.invoke(obj, new Object[] {"xxxx"});
        System.out.println(result); // 此时result是Integer类型

    到此,反射机制完毕,Spring里面通过配置文件也是差不多的,能够通过配置文件读取到方法和属性,加以运用。

    下面是实例的两份完整代码:

    package com.sun;
    
    /**
     * A base class having some attributes and methods
     * @author Octobershiner
     * @since 2012 3 17
     * 
     * */
    public class Role {
        public String age = "10";
        private String name = "Hello world";
        private String type;
        
        // Constructors
        public Role(){
            System.out.println("Constructor Role() is invoking");
        }
        //私有构造器
        private Role(String name){
            this.name = name;
            System.out.println("Constructor Role(String name) is invoking.");
        }
        
        //get and set method
        
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public String getType() {
            return type;
        }
        public void setType(String type) {
            this.type = type;
        }
        
        //override the toString method to show the class
        public String toMyString(String xxx){
            return "This is a role called "+xxx;
        }
        
    }

    package com.sun;
    
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.lang.reflect.Modifier;
    
    import org.omg.Dynamic.Parameter;
    
    public class TESTreflection {
        
        
        
        public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, SecurityException, NoSuchMethodException, IllegalArgumentException, InvocationTargetException, NoSuchFieldException {
            
    //例程1:获取方法
            //获得类类型的两种方式
            Class classType = Class.forName("com.sun.Role");
          //返回class对象所对应的类或接口中,所声明的所有方法的数组(包括私有方法)
    
            
          System.out.println("classType="+classType.getSimpleName());  //类名
          System.out.println("classType="+classType.getCanonicalName());//类的全名
    
        //例程2:创建对象
          Object obj = classType.newInstance();
      
        //获取属性:分为所有的属性和指定的属性:
          Field[] fs = classType.getDeclaredFields();  
        //定义可变长的字符串,用来存储属性  
          StringBuffer sb = new StringBuffer();  
          
          sb.append(Modifier.toString(classType.getModifiers()) + " class " + classType.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);  
      
          
        //获取age属性  
         Field age = classType.getDeclaredField("age"); 
         Field name = classType.getDeclaredField("name"); 
        //打破封装   
         age.setAccessible(true); //使用反射机制可以打破封装性,导致了java对象的属性不安全。  
         name.setAccessible(true);
         System.out.println("Role class age is = "+age.get(obj));  
         System.out.println("Role class age is = "+name.get(obj));  
         age.set(obj, "110"); //set  
         System.out.println("Role class age is = "+age.get(obj));  
         
         
        Method[] methods = classType.getDeclaredMethods();
        StringBuffer sb2 = new StringBuffer();
        //遍历输出所有方法声明
        for(Method method : methods)
         {
            sb2.append("	");//空格  
            sb2.append(Modifier.toString(method.getModifiers())+"  ");//获得方法的类型
            sb2.append(method.getReturnType().getSimpleName().toString()+"  ");//获得方法的返回类型
            sb2.append(method.getName()+"();
    ");//获取方法名
        }
        System.out.println(sb2);
        
        
        // 通过反射调用方法
        //调用方法一:
        // 首先需要获得与该方法对应的Method对象
        Method toMyStringMethod = classType.getDeclaredMethod("toMyString",new Class[]{String.class});  
        toMyStringMethod.setAccessible(true);
        Object result2 = toMyStringMethod.invoke(obj, new Object[]{"sun"});//为该方法传入参数
        System.out.println(result2.toString());
        //调用方法二:
        Method toMyStringMethod1 = classType.getMethod("toMyString",new Class[]{String.class});  
        Object result = toMyStringMethod1.invoke(obj, new Object[] {"xxxx"});
        System.out.println(result); // 此时result是Integer类型
        
        
    /* //例程2:通过反射调用方法
            
            // 生成新的对象:用newInstance()方法
            Class<?> classType2 = classType.getName().toString();
            
            
            // 通过反射调用方法
            // 首先需要获得与该方法对应的Method对象
            Method echoMethod = role.getDeclaredMethod("echo", new Class[]{String.class});
     */    
            
            
            
    
        }
    }
  • 相关阅读:
    Golang Channel用法简编
    一个有关Golang变量作用域的坑
    Goroutine是如何工作的
    Go语言是如何处理栈的
    Go与C语言的互操作
    Lua虚拟机初始化
    lua 函数调用 -- 闭包详解和C调用
    c++对象导出到lua
    nginx缓存设置proxy_cache
    golang中map并发读写问题及解决方法
  • 原文地址:https://www.cnblogs.com/sunxun/p/5281175.html
Copyright © 2011-2022 走看看