Java语言的反射机制

在JAVA运行环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一个对象,能否调用它的任意一个方法?答案是肯定的。

这种动态获取类的信息以及动态调用类的对象的方法的功能来自于Java语言的反射(Reflection)机制。

JAVA反射机制主要提供了以下功能:

1、在运行时判断任意一个对象所属的类

2、在运行时构造任意一个类的对象

3、在运行时判断任意一个类所具有的成员变量和方法

4、在运行时调用任意一个对象的方法

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

一般而言,开发者群社群说到动态语言,大致认同的一个定义是:“程序运行时,允许改变程序结构或变量类型,这种语言被称为动态语言”。从这个观点看,Perl,Python,Ruby是动态语言,而C++,Java,C#不是动态语言。

尽管在这样的定义与分类下Java不是动态语言,它却有着一个非常突出的动态相关机制:Reflection。这个字的意思是“反射、映像、倒影”,用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括method定义,也就是不能获得方法里的具体代码),并生成其对象的实体、或对其fields设值、或唤起其methods。这种“看透class”的能力(the ablility of the program to examine itself)被称为introspection(内省、内观、反省)。Reflection和introspection是常被并提的两个术语。

在JDK中,主要由以下类来实现JAVA反射机制, 这些类都位于java.lang.reflect包中

1、Class类:代表一个类

2、Field类:代表类的成员变量(成员变量也称为类的属性)

3、Method类:代表类的方法

4、Constructor类:代表类的构造方法

5、Array类:提供了动态创建数组,以及访问数组的元素的静态方法

反射机制示例代码一、

java 代码
  1. package com.test.reflect;   
  2.   
  3. import java.lang.reflect.Method;   
  4.   
  5. public class ReflectTest {   
  6.   
  7.     public static void main(String[] args) throws Exception {   
  8.            
  9.         //加载并初始化命令行参数指定的类   
  10.         Class clazz = Class.forName(args[0]);//args[0]为:java.lang.String   
  11.            
  12.         //获得类的所有方法   
  13.         Method[] methods = clazz.getDeclaredMethods();   
  14.         for(Method method:methods)   
  15.         {   
  16.             System.out.println(method.toString());   
  17.         }   
  18.   
  19.     }   
  20.   
  21. }   

 

输出结果为:

public int java.lang.String.hashCode()
public int java.lang.String.compareTo(java.lang.String)
public volatile int java.lang.String.compareTo(java.lang.Object)
public int java.lang.String.indexOf(int,int)
public int java.lang.String.indexOf(int)
public int java.lang.String.indexOf(java.lang.String)
public int java.lang.String.indexOf(java.lang.String,int)
static int java.lang.String.indexOf(char[],int,int,char[],int,int,int)
public boolean java.lang.String.equals(java.lang.Object)
public java.lang.String java.lang.String.toString()
public char java.lang.String.charAt(int)
private static void java.lang.String.checkBounds(byte[],int,int)
public int java.lang.String.codePointAt(int)
public int java.lang.String.codePointBefore(int)
public int java.lang.String.codePointCount(int,int)
public int java.lang.String.compareToIgnoreCase(java.lang.String)
public java.lang.String java.lang.String.concat(java.lang.String)
public boolean java.lang.String.contains(java.lang.CharSequence)
public boolean java.lang.String.contentEquals(java.lang.StringBuffer)
public boolean java.lang.String.contentEquals(java.lang.CharSequence)
public static java.lang.String java.lang.String.copyValueOf(char[],int,int)
public static java.lang.String java.lang.String.copyValueOf(char[])
public boolean java.lang.String.endsWith(java.lang.String)
public boolean java.lang.String.equalsIgnoreCase(java.lang.String)
public static transient java.lang.String java.lang.String.format(java.util.Locale,java.lang.String,java.lang.Object[])
public static transient java.lang.String java.lang.String.format(java.lang.String,java.lang.Object[])
public byte[] java.lang.String.getBytes()
public byte[] java.lang.String.getBytes(java.lang.String) throws java.io.UnsupportedEncodingException
public void java.lang.String.getBytes(int,int,byte[],int)
void java.lang.String.getChars(char[],int)
public void java.lang.String.getChars(int,int,char[],int)
public native java.lang.String java.lang.String.intern()
static int java.lang.String.lastIndexOf(char[],int,int,char[],int,int,int)
public int java.lang.String.lastIndexOf(int)
public int java.lang.String.lastIndexOf(int,int)
public int java.lang.String.lastIndexOf(java.lang.String,int)
public int java.lang.String.lastIndexOf(java.lang.String)
public int java.lang.String.length()
public boolean java.lang.String.matches(java.lang.String)
public int java.lang.String.offsetByCodePoints(int,int)
public boolean java.lang.String.regionMatches(boolean,int,java.lang.String,int,int)
public boolean java.lang.String.regionMatches(int,java.lang.String,int,int)
public java.lang.String java.lang.String.replace(java.lang.CharSequence,java.lang.CharSequence)
public java.lang.String java.lang.String.replace(char,char)
public java.lang.String java.lang.String.replaceAll(java.lang.String,java.lang.String)
public java.lang.String java.lang.String.replaceFirst(java.lang.String,java.lang.String)
public java.lang.String[] java.lang.String.split(java.lang.String,int)
public java.lang.String[] java.lang.String.split(java.lang.String)
public boolean java.lang.String.startsWith(java.lang.String)
public boolean java.lang.String.startsWith(java.lang.String,int)
public java.lang.CharSequence java.lang.String.subSequence(int,int)
public java.lang.String java.lang.String.substring(int)
public java.lang.String java.lang.String.substring(int,int)
public char[] java.lang.String.toCharArray()
public java.lang.String java.lang.String.toLowerCase()
public java.lang.String java.lang.String.toLowerCase(java.util.Locale)
public java.lang.String java.lang.String.toUpperCase(java.util.Locale)
public java.lang.String java.lang.String.toUpperCase()
public java.lang.String java.lang.String.trim()
public static java.lang.String java.lang.String.valueOf(char[])
public static java.lang.String java.lang.String.valueOf(char)
public static java.lang.String java.lang.String.valueOf(int)
public static java.lang.String java.lang.String.valueOf(long)
public static java.lang.String java.lang.String.valueOf(float)
public static java.lang.String java.lang.String.valueOf(double)
public static java.lang.String java.lang.String.valueOf(java.lang.Object)
public static java.lang.String java.lang.String.valueOf(boolean)
public static java.lang.String java.lang.String.valueOf(char[],int,int)

 

示例代码二、实现对象的拷贝

java 代码
  1. package com.test.reflect;   
  2.   
  3. import java.lang.reflect.Field;   
  4. import java.lang.reflect.Method;   
  5.   
  6. /**  
  7.  * 实现对象的拷贝  
  8.  * @author yahaitt  
  9.  *  
  10.  */  
  11. public class ReflectCopyTest {   
  12.   
  13.     public Object copy(Object object) throws Exception   
  14.     {   
  15.         //获得对象的类型   
  16.         Class clazz_old = object.getClass();   
  17.            
  18.         //通过默认构造方法创建一个新的对象   
  19.         //1、需要注意的是getConstructor(new Class[]{})中的参数的个数必须和newInstance(new Object[]{})中的参数是一致的   
  20.         //2、通过class类的newInstance生成新对象只能通过不带参数的构造方法,如: Object o = clazz_old.newInstance();,如果clazz_old对应的类没有默认的不带参数的构造方法,则这里就会抛错。   
  21.         //3、通过Constructor的newInstance生成新对象可以通过带各种参数的构造方法,但是必须对应的类要存在这些构造方法,如果一个都没有,它并不会去调用默认的不带参数的构造方法,如果要去调用不带参数的构造方法,一定要在类里显式定义   
  22.         Object object_new = clazz_old.getConstructor(new Class[]{}).newInstance(new Object[]{});   
  23.            
  24.         //获得对象的所有属性   
  25.         Field[] fields = clazz_old.getDeclaredFields();   
  26.         for(Field field : fields)   
  27.         {   
  28.             String fieldName = field.getName();   
  29.             String firstLatter = fieldName.substring(0,1);   
  30.                
  31.             //获得和属性对应的getXXX()方法的名字   
  32.             String getMethodStr = "get" + firstLatter.toUpperCase() + fieldName.substring(1);   
  33.             //获得和属性对应的setXXX()方法的名字   
  34.             String setMethodStr = "set" + firstLatter.toUpperCase() + fieldName.substring(1);   
  35.                
  36.             //获得和属性对应的getXXX()方法   
  37.             Method getMethod = clazz_old.getMethod(getMethodStr, new Class[]{});   
  38.             //获得和属性对应的setXXX()方法   
  39.             Method setMethod = clazz_old.getMethod(setMethodStr, field.getType());   
  40.                
  41.             //调用原对象的getXXX()方法   
  42.             Object value = getMethod.invoke(object, new Object[]{});   
  43.             //调用拷贝对象的setXXX()方法   
  44.             setMethod.invoke(object_new, value);   
  45.         }   
  46.            
  47.         return object_new;   
  48.            
  49.     }   
  50.        
  51.     public static void main(String[] args) throws Exception {   
  52.            
  53.         ReflectCopyTest test = new ReflectCopyTest();   
  54.         Custom custom = new Custom();   
  55.         custom.setId(1);   
  56.         custom.setName("yahaitt");   
  57.         custom.setAge(20);   
  58.         Custom copy = (Custom) test.copy(custom);   
  59.         System.out.println(copy.getId());   
  60.         System.out.println(copy.getName());   
  61.         System.out.println(copy.getAge());   
  62.     }   
  63.   
  64. }   
  65.   
  66. class Custom   
  67. {   
  68.     private int id;   
  69.     private String name;   
  70.     private int age;   
  71.        
  72.     public Custom()   
  73.     {   
  74.            
  75.     }   
  76.        
  77.     public int getId() {   
  78.         return id;   
  79.     }   
  80.     public void setId(int id) {   
  81.         this.id = id;   
  82.     }   
  83.     public String getName() {   
  84.         return name;   
  85.     }   
  86.     public void setName(String name) {   
  87.         this.name = name;   
  88.     }   
  89.     public int getAge() {   
  90.         return age;   
  91.     }   
  92.     public void setAge(int age) {   
  93.         this.age = age;   
  94.     }   
  95.        
  96.        
  97. }   

输出结果是:

1
yahaitt
20

示例代码三、invoke的应用:

java 代码
  1. package com.test.reflect;   
  2.   
  3. import java.lang.reflect.Method;   
  4.   
  5. public class InvokeTest {   
  6.        
  7.     public int add(int a, int b)   
  8.     {   
  9.         return a + b;   
  10.     }   
  11.        
  12.     public String echo(String msg)   
  13.     {   
  14.         return "echo:" + msg;   
  15.     }   
  16.        
  17.     public static void main(String[] args) throws Exception {   
  18.            
  19.         Class<?> clazz = InvokeTest.class;   
  20.         Object test = clazz.newInstance();   
  21.            
  22.         Method addMethod =clazz.getMethod("add"new Class[]{int.classint.class});   
  23.         Method echoMethod = clazz.getMethod("echo"new Class[]{String.class});   
  24.            
  25.         // 调用InvokeTester对象的add()方法   
  26.         Object addValue = addMethod.invoke(test, new Object[]{new Integer(200), new Integer(100)});   
  27.         System.out.println((Integer)addValue);   
  28.            
  29.         // 调用InvokeTester对象的echo()方法   
  30.         Object echoValue = echoMethod.invoke(test, new Object[]{new String("hello")});   
  31.         System.out.println((String)echoValue);   
  32.            
  33.     }   
  34.   
  35. }   

 

输出结果是:

300
echo:hello

对示例三的说明:

1、add()方法的两个参数为int 类型,获得表示add()方法的Method对象的代码如下:
Method addMethod=clazz.getMethod("add",new Class[]{int.class,int.class});
Method类的invoke(Object obj,Object args[])方法接收的参数必须为对象,如果参数为基本类型数据,必须转换为相应的包装类型的对象。invoke()方法的返回值总是对象,如果实际被调用的方法的返回类型是基本类型数据,那么invoke()方法会把它转换为相应的包装类型的对象,再将其返回

2、在本例中,尽管InvokeTest 类的add()方法的两个参数以及返回值都是int类型,调用add Method 对象的invoke()方法时,只能传递Integer 类型的参数,并且invoke()方法的返回类型也是Integer 类型,Integer 类是int 基本类型的包装类:

Object result=addMethod.invoke(test,
new Object[]{new Integer(100),new Integer(200)});
System.out.println((Integer)result); //result 为Integer类型

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值