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() +"{\n");  
      
      for(Field field:fs){  
          sb.append("\t");//空格  
          sb.append(Modifier.toString(field.getModifiers())+" ");//获得属性的修饰符,例如public,static等等  
          sb.append(field.getType().getSimpleName() + " ");//属性的类型的名字  
          sb.append(field.getName()+";\n");//属性的名字+回车  
      }  
      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("\t");//空格  
        sb2.append(Modifier.toString(method.getModifiers())+"  ");//获得方法的类型
        sb2.append(method.getReturnType().getSimpleName().toString()+"  ");//获得方法的返回类型
        sb2.append(method.getName()+"();\n");//获取方法名
    }
    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() +"{\n");  
      
      for(Field field:fs){  
          sb.append("\t");//空格  
          sb.append(Modifier.toString(field.getModifiers())+" ");//获得属性的修饰符,例如public,static等等  
          sb.append(field.getType().getSimpleName() + " ");//属性的类型的名字  
          sb.append(field.getName()+";\n");//属性的名字+回车  
      }  
      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("\t");//空格  
        sb2.append(Modifier.toString(method.getModifiers())+"  ");//获得方法的类型
        sb2.append(method.getReturnType().getSimpleName().toString()+"  ");//获得方法的返回类型
        sb2.append(method.getName()+"();\n");//获取方法名
    }
    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});
 */    
        
        
        

    }
}

 

posted on 2016-03-15 21:06  手撕高达的村长  阅读(202)  评论(0编辑  收藏  举报

导航