现在的位置: 首页 > 综合 > 正文

Java学习整理系列之Java反射机制

2018年02月06日 ⁄ 综合 ⁄ 共 6135字 ⁄ 字号 评论关闭

JAVA语言中的反射机制:
    在Java 运行时 环境中,对于任意一个类,能否知道这个类有哪些属性和方法?
    对于任意一个对象,能否调用他的方法?这些答案是肯定的,这种动态获取类的信息,以及动态调用类的方法的功能来源于JAVA的反射。从而使java具有动态语言的特性。

  JAVA反射机制主要提供了以下功能:
      1.在运行时判断任意一个对象所属的类
      2.在运行时构造任意一个类的对象
      3.在运行时判断任意一个类所具有的成员变量和方法(通过反射甚至可以调用private方法)
      4.在运行时调用任意一个对象的方法(*****注意:前提都是在运行时,而不是在编译时)

  Java 反射相关的API简介:
      位于java。lang。reflect包中
        --Class类:代表一个类
        --Filed类:代表类的成员变量
        --Method类:代表类的方法
        --Constructor类:代表类的构造方法
        --Array类:提供了动态创建数组,以及访问数组的元素的静态方法。该类中的所有方法都是静态方法


----Class类
     在 java 的Object类中的申明了数个应该在所有的java类中被改写的methods:
hashCode(), equals(),clone(),toString(),getClass()等,其中的getClass()返回一个
Class 类型的对象。
     Class类十分的特殊,它和一般的类一样继承自Object,其实体用以表达java程序运行
时的 class和 interface,也用来表达 enum,array,primitive,Java Types 以及关键字void
,当加载一个类,或者当加载器(class loader)的defineClass()被JVM调用,便产生一个Class
对象,
     Class是Reflection起源,针对任何你想探勘的class(类),唯有现为他产生一个Class
的对象,接下来才能经由后者唤起为数十多个的反射API。

java.lang.Class 

static Class forName(String className)返回描述类名为className的Class对象
Object newInstance()返回一个类的一个新实例
Field[] getFields()返回包含Field对象的数组,这些对象记录了这个类或者其超类的公共域
Field[] getDeclaredField()返回包含Field对象的数组,这些对象记录了这个类的全部域

Method[] getMethods()返回这个类或者其超类所有的公有方法
Method[] getDeclareMethods()返回这个类或者接口的所有方法,不包括超类继承的方法
Constructor[] getConstructors()返回所有包含了Class对象所描述类的公有构造器
Constructor[] getDeclaredConstructors()返回包含了Class对象所描述的类的所有构造器

Java.lang.reflect.Constructor

Class[] getParameterTypes()返回一个用于描述参数类型的Class对象数组
getReturnType()返回一个用于描述返回类型的Class对象 
int getModifiers()这个方法就是返回一个int型的返回值,代表类、成员变量、方法的修饰符。

通过返回的int类型的值,还是很难判断这些变量有哪些修饰符。在这里,需要用到java.lang.reflect.Modifier这个类。Modifier提供了很多静态方法。
如public static String toString(int mod)就可以输出该整数对应的所有的修饰符。public static boolean isPublic(int mod)就可以判断该整数对应的是不是包含public修饰符。

Class getDeclaringClass() 返回一个用于描述类中定义的构造器、方法或域的Class对象

     Java允许我们从多种途径为一个类class生成对应的Class对象。
          --运用 getClass():Object类中的方法,每个类都拥有此方法 
                                String str="abc";
                                Class cl=str.getClass();


         --运用 Class.getSuperclass():Class类中的方法,返回该Class的父类的Class
         --运用 Class.forName()静态方法:
         --运用 ,Class:类名.class
         --运用primitive wrapper classes的TYPE语法: 基本类型包装类的TYPE,如:Integer.TYPE
                      注意:TYPE的使用,只适合原生(基本)数据类型

----运行时生成instance
     想生成对象的实体,在反射动态机制中有两种方法,一个针对无变量的构造方法,一个针对带参数的
构造方法,,如果想调用带参数的构造方法,就比较的麻烦,不能直接调用Class类中的newInstance()
,而是调用Constructor类中newInstance()方法,首先准备一个Class[]作为Constructor的参数类型。
然后调用该Class对象的getConstructor()方法获得一个专属的Constructor的对象,最后再准备一个
Object[]作为Constructor对象昂的newInstance()方法的实参。
      在这里需要说明的是 只有两个类拥有newInstance()方法,分别是Class类和Constructor类
Class类中的newInstance()方法是不带参数的,而Constructro类中的newInstance()方法是带参数的
需要提供必要的参数。
    例:
      Class c=Class.forName("DynTest");
      Class[] ptype=new Class[]{double.class,int.class};
      Constructor ctor=c.getConstructor(ptypr);
      Object[] obj=new Object[]{new Double(3.1415),new Integer(123)};
      Object object=ctor.newInstance(obj);
      System.out.println(object);

----运行时调用Method
    这个动作首先准备一个Class[]{}作为getMethod(String name,Class[])方法的参数类型,接下来准备一个
Obeject[]放置自变量,然后调用Method对象的invoke(Object obj,Object[])方法。
     

----运行时调用Field内容
    变更Field不需要参数和自变量,首先调用Class的getField()并指定field名称,获得特定的Field对象后
便可以直接调用Field的 get(Object obj)和set(Object obj,Object value)方法

java 代码

import java.lang.reflect.Field;   
import java.lang.reflect.InvocationTargetException;   
import java.lang.reflect.Method;   
  
public class Test {   
  
    /**  
     * 在这个类里面存在有copy()方法,根据指定的方法的参数去 构造一个新的对象的拷贝  
     * 并将他返回  
     * @throws NoSuchMethodException   
     * @throws InvocationTargetException   
     * @throws IllegalAccessException   
     * @throws InstantiationException   
     * @throws SecurityException   
     * @throws IllegalArgumentException   
     */  
    public Object copy(Object obj) throws IllegalArgumentException, SecurityException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException{   
        //获得对象的类型   
        Class classType=obj.getClass();   
        System.out.println("该对象的类型是:"+classType.toString());        
        //通过默认构造方法去创建一个新的对象,getConstructor的视其参数决定调用哪个构造方法   
        Object objectCopy=classType.getConstructor(new Class[]{}).newInstance(new Object[]{});        
        //获得对象的所有属性   
        Field[] fields=classType.getDeclaredFields();      
        for(int i=0;i<fields.length;i++){
            //获取数组中对应的属性   
            Field field=fields[i];   
            String fieldName=field.getName();   
            String stringLetter=fieldName.substring(0, 1).toUpperCase();   
            //获得相应属性的getXXX和setXXX方法名称   
            String getName="get"+stringLetter+fieldName.substring(1);   
            String setName="set"+stringLetter+fieldName.substring(1);     
            //获取相应的方法   
            Method getMethod=classType.getMethod(getName, new Class[]{});   
            Method setMethod=classType.getMethod(setName, new Class[]{field.getType()});     
            //调用源对象的getXXX()方法   
            Object value=getMethod.invoke(obj, new Object[]{});   
            System.out.println(fieldName+" :"+value);   
            //调用拷贝对象的setXXX()方法   
            setMethod.invoke(objectCopy,new Object[]{value});       
        }        
        return objectCopy;         
    }   
           
    public static void main(String[] args) throws IllegalArgumentException, SecurityException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {   
        Customer customer=new Customer();   
        customer.setName("hejianjie");   
        customer.setId(new Long(1234));   
        customer.setAge(19);        
        Customer customer2=null;   
        customer2=(Customer)new Test().copy(customer);   
        System.out.println(customer.getName()+" "+customer2.getAge()+" "+customer2.getId());       
        System.out.println(customer);   
        System.out.println(customer2);   
    }   
  
}   
class Customer{      
    private Long id;     
    private String name;       
    private int age;        
    public Customer(){        
    }   
    public int getAge() {   
        return age;   
    }   
    public void setAge(int age) {   
        this.age = age;   
    }   
    public Long getId() {   
        return id;   
    }   
    public void setId(Long id) {   
        this.id = id;   
    }   
    public String getName() {   
        return name;   
    }   
    public void setName(String name) {   
        this.name = name;   
    }       
}  

java.lang.reflect.Array

static Object set(Object array, int index, Object newValue)
satic Object setXxx(Object array, int index, Xxx newValue)
这些方法将一个新值存储到给定位置上的给定数组中。
其中xxx代表boolean、btye 、double、float、int、long、short中的其中一种


static Object get(object array, int index)
static xxx getXxx(Object array, int index)
这些方法将返回存储在给定位置上的给定数组的内容。

java 代码

package cn.com.reflection;   
  
import java.lang.reflect.Array;   
  
public class ArrayTester1 {   
  
    /**  
     * 此类根据反射来创建  
     * 一个动态的数组   
     */  
    public static void main(String[] args) throws ClassNotFoundException {   
           
        Class classType=Class.forName("java.lang.String");   
           
        Object array= Array.newInstance(classType,10);  //指定数组的类型和大小   
           
         //对索引为5的位置进行赋值   
        Array.set(array, 5, "hello");   
           
        String s=(String)Array.get(array, 5);   
           
        System.out.println(s);   
           
           
        //循环遍历这个动态数组   
        for(int i=0;i<((String[])array).length;i++){   
               
            String str=(String)Array.get(array, i);   
               
            System.out.println(str);   
        }   
  
    }   
  
}   

抱歉!评论已关闭.