java中的反射机制详解
在Java运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一个对象,能否调用它的任意一个方法?答案是肯定的。这种动态获取类的信息,以及动态调用对象的方法的功能来自于Java语言的反射(Reflection)机制。Java反射机制主要提供了以下功能:
1.在运行时判断任意一个对象所属的类;
2.在运行时构造任意一个类的对象;(在编译时通过new()方法就可以构造一个类的对象)
3.在运行时判断任意一个类所具有的成员变量和方法;
4.在运行时调用任意一个对象的方法;
5.生成动态代理。
Reflection 是 Java 被视为动态(或准动态)语言的关键,允许程序于执行期利用Reflection APIs 取得任何已知名称之 class 的內部信息,包括 package、type、parameters、superclass、implemented interfaces、inner classes、 outer class、fields、constructors、methods、modifiers(如public,static等),并可于运行期生成instances、改变 fields 內容或调用methods(包括私有的方法,即通过反射我们可以打破类的包装机制)。
一般而言,开发者社区说到动态语言,大致认同的一个定义是:“程序运行时,允许改变程序结构和变量类型,这种语言就称为动态语言。”从这个观点看,perl,python,ruby,javascript等是动态语言,c,c++,c#,java等都不是动态语言。
尽管在这样的定义与分类下,java并不是动态语言,但他却有着一个非常突出的动态相关机制:Reflection。这个字的意思是“反射、映射、倒影”,用在java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或调用其methods。这种“看透 class”的能力(the ability of the program to examine itself)被称为introspection(内省、内观、反省)。Reflection和introspection是常被并提的两个术语。
在JDK中,主要由以下类来实现Java反射机制,这些类都位于java.lang.reflect包中。
- Class类:代表一个类。(位于java.lang)
- Field类:代表类的成员变量(成员变量也称为类的属性)。
- Method类:代表类的方法。
- Constructor类:代表类的构造方法。
- Array类:提供了动态创建数组,以及访问数组元素的静态方法。
Field类: | 提供有关类或接口的属性的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)属性或实例属性,简单的理解可以把它看成一个封装反射类的属性的类。 |
Constructor类: | 提供关于类的单个构造方法的信息以及对它的访问权限。这个类和Field类不同,Field类封装了反射类的属性,而Constructor类则封装了反射类的构造方法。 |
Method类: | 提供关于类或接口上单独某个方法的信息。所反映的方法可能是类方法或实例方法(包括抽象方法)。 这个类不难理解,它是用来封装反射类方法的一个类。 |
Class类: | 类的实例表示正在运行的 Java 应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。 |
Object类: | 每个类都使用 Object 作为超类。所有对象(包括数组)都实现这个类的方法。 |
在java中,无论生成某个类的多少个对象,这些对象都对应于同一个class对象。
要想使用反射,首先要获得对应类或对象的Class对象,获取某个类或对象的Class对象的三种方法:
1. 使用Class类的静态方法:Class<?> classType = Class.forName("java.lang.String");
2. 使用类的.class语法:Class<?> classType = String.class;
3. 适用对象的getClass()方法:String s = "aa"; Class<?> classType = s.getClass();
若想通过反射来生成类的对象,有以下两种方式:
1. 先生成欲生成对象对应的Class对象,然后通过Class对象的newInstance()方法直接生成新的实例对象:
Class<?> classType = String.class;
String str = classType.newInstance();
2. 先生成欲生成对象对应的Class对象,然后通过Class对象的getConstructor()方法生成构造方法对象,再通过该构造方法对象来生成新的实例对象:
Class<?> classType = String.class;
Constructor<?> constructor = classType.getConstructor();
String str = constructor.newInstance();
其中后者可以通过给getConstructor()方法传递参数而指定特定的构造方法(前者只能使用默认的即参数为空的构造方法):
Class<?> classType = object.getClass();
Constructor<?> constructor = classType.getConstructor(new Class[]{String.class, int.class});
Object obj = constructor.newInstance(new Object[]{"tom", 23});
1 import java.lang.reflect.Field; 2 import java.lang.reflect.Method; 3 4 5 public class ReflectTest { 6 public Object copy (Object object) throws Exception{ 7 Class<?> classType = object.getClass(); 8 Object objectCopy = classType.getConstructor(new Class[]{}) 9 .newInstance(new Object[]{}); 10 Field[] fields = classType.getDeclaredFields(); 11 for(Field field: fields) { 12 String name = field.getName(); 13 String firstLetter = name.substring(0, 1).toUpperCase(); 14 String setMethodName = "set" + firstLetter + name.substring(1); 15 String getMethodName = "get" + firstLetter + name.substring(1); 16 Method setMethod = classType.getMethod(setMethodName, new Class[]{field.getType()}); 17 Method getMethod = classType.getMethod(getMethodName, new Class[]{}); 18 setMethod.invoke(objectCopy, new Object[]{getMethod.invoke(object, new Object[]{})}); 19 } 20 return objectCopy; 21 } 22 23 public static void main(String[] args) throws Exception{ 24 Customer customer = new Customer("Tom", 23); 25 customer.setId(1L); 26 ReflectTest reflectTest = new ReflectTest(); 27 Customer customer2 = (Customer)reflectTest.copy(customer); 28 System.out.println(customer2.getId() + "," + customer2.getName() + "," + customer2.getAge()); 29 } 30 } 31 32 class Customer { 33 private Long id; 34 private String name; 35 private int age; 36 37 public Customer() { 38 } 39 40 public Customer(String name, int age) { 41 this.name = name; 42 this.age = age; 43 } 44 45 public Long getId() { 46 return id; 47 } 48 49 public void setId(Long id) { 50 this.id = id; 51 } 52 53 public String getName() { 54 return name; 55 } 56 57 public void setName(String name) { 58 this.name = name; 59 } 60 61 public int getAge() { 62 return age; 63 } 64 65 public void setAge(int age) { 66 this.age = age; 67 } 68 }
作者:beanmoon
出处:http://www.cnblogs.com/beanmoon/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。
该文章也同时发布在我的独立博客中-豆月博客。