Java反射学习 收藏
出处:http://wangchun8926.javaeye.com/blog/852830
今天抽空看了一下Java反射,反射对于后面理解struts、hibernate、spring等框架非常重要,因为这些框架的源代码里面大量的使用到了反射机制.那么,什么是反射呢?
反射就是指可以在程序运行时知道一个类的属性、方法、其父类、接口等相关信息.我们知道一个类可以有多个对象实例,那么我们类也可以当作某个更抽象类的实例,这个更抽象类的类就是Class类,这个类在java.lang包中,他由JVM实例化,如下:
- public final
- class Class<T> implements java.io.Serializable,
- java.lang.reflect.GenericDeclaration,
- java.lang.reflect.Type,
- java.lang.reflect.AnnotatedElement
public final class Class<T> implements java.io.Serializable, java.lang.reflect.GenericDeclaration, java.lang.reflect.Type, java.lang.reflect.AnnotatedElement
可以看到这个类是final的,不允许被我们继承,在这个类里面定义了一系列的方法帮助我们在程序运行时获得类的相关信息,下面先看一下一个hello world
- public class ReflectTest1 {
- public static void main(String[] args) throws Exception{
- Class clazz = ReflectTest1.class;
- }
- }
public class ReflectTest1 { public static void main(String[] args) throws Exception{ Class clazz = ReflectTest1.class; }}
这个clazz就封装了ReflectTest的一些类型信息
下面再看一下利用反射来动态调用方法:
- public class ReflectTest1 {
- public String print(String message) {
- return "hello : "+message;
- }
- public static void main(String[] args) throws Exception{
- Class clazz = ReflectTest1.class;
- Object obj = clazz.newInstance();//实例化ReflectTest
- Method echoMethod = clazz.getMethod("print",String.class);
- //得到ReflectTest的print方法
- Object res = echoMethod.invoke(obj,new Object[]{"javaeye"});//调用print方法,res为该方法的返回值
- System.out.println((String)res);//打印该返回值
- }
- }
public class ReflectTest1 {public String print(String message) {return "hello : "+message;}public static void main(String[] args) throws Exception{Class clazz = ReflectTest1.class;Object obj = clazz.newInstance();//实例化ReflectTestMethod echoMethod = clazz.getMethod("print",String.class);//得到ReflectTest的print方法Object res = echoMethod.invoke(obj,new Object[]{"javaeye"});//调用print方法,res为该方法的返回值System.out.println((String)res);//打印该返回值}}
注意上面的getMethod方法,第一个参数为需要得到的方法名称,后面是一个可变参数,代表方法参数的类型信息.为什么要用一个可变参数,而不直接通过方法名称得到方法呢?因为一个类可以重载方法,所以必须知道方法的参数类型才能确定得到的是哪个方法.
今天继续学习了java反射1.对象的拷贝功能
- class People {
- private Long id;
- private String name;
- private Integer age;
- public People() {
- }
- public People(Long id,String name,Integer age) {
- this.setId(id);
- this.setName(name);
- this.setAge(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;
- }
- public Integer getAge() {
- return age;
- }
- public void setAge(Integer age) {
- this.age = age;
- }
- }
class People {private Long id;private String name;private Integer age;public People() {}public People(Long id,String name,Integer age) {this.setId(id);this.setName(name);this.setAge(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;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}}
import java.lang.reflect.Constructor;
- import java.lang.reflect.Field;
- import java.lang.reflect.Method;
- public class ReflectTest3 {
- private static Object copy(Object obj) throws Exception {
- Class clazz = obj.getClass();
- Constructor cons = clazz.getConstructor(new Class[]{});//得到空的构造方法
- Object copyObj = cons.newInstance(new Object[]{});//间接调用空构造方法实例化copyObj
- Field[] fields = clazz.getDeclaredFields();//得到源对象的成员变量(该方法可得到私有的成员变量)
- for(Field field : fields) {
- String filedName = field.getName();
- //得到set、get方法
- String firstLetter = filedName.substring(0,1).toUpperCase();
- String getMethodName = "get"+firstLetter+filedName.substring(1);//得到get方法名称
- String setMethodName = "set"+firstLetter+filedName.substring(1);//得带get方法名称
- Method getMethod = clazz.getMethod(getMethodName,new Class[]{});
- Method setMethod = clazz.getMethod(setMethodName,field.getType());//得到set方法本身
- Object res = getMethod.invoke(obj,new Object[]{});//调用源对象的get方法
- setMethod.invoke(copyObj,res);
- }
- return copyObj;
- }
- public static void main(String[] args) throws Exception {
- People p = (People)copy(new People(1L,"张三",20));
- System.out.println(p.getId()+";"+p.getName()+";"+p.getAge());
- }
- }
import java.lang.reflect.Field;import java.lang.reflect.Method;public class ReflectTest3 {private static Object copy(Object obj) throws Exception {Class clazz = obj.getClass();Constructor cons = clazz.getConstructor(new Class[]{});//得到空的构造方法Object copyObj = cons.newInstance(new Object[]{});//间接调用空构造方法实例化copyObjField[] fields = clazz.getDeclaredFields();//得到源对象的成员变量(该方法可得到私有的成员变量)for(Field field : fields) {String filedName = field.getName();//得到set、get方法String firstLetter = filedName.substring(0,1).toUpperCase();String getMethodName = "get"+firstLetter+filedName.substring(1);//得到get方法名称String setMethodName = "set"+firstLetter+filedName.substring(1);//得带get方法名称Method getMethod = clazz.getMethod(getMethodName,new Class[]{});Method setMethod = clazz.getMethod(setMethodName,field.getType());//得到set方法本身Object res = getMethod.invoke(obj,new Object[]{});//调用源对象的get方法setMethod.invoke(copyObj,res);}return copyObj;}public static void main(String[] args) throws Exception {People p = (People)copy(new People(1L,"张三",20));System.out.println(p.getId()+";"+p.getName()+";"+p.getAge());}}
用getConstructor方法时需要在类People中显示声明一个无参构造方法,尽管在Java中默认会隐式声明一个无参构造方法,
否则会抛出一个NoSuchMethod异常.getDeclaredFields方法可以得到private访问权限的成员变量,但只是只读的,不能
行修改,那怎样可以对私有属性的修改呢?
2.对私有属性的修改
- public class PrivateClass {
- private String name = "csdn";
- public String getName() {
- return this.name;
- }
- }
public class PrivateClass {private String name = "csdn";public String getName() {return this.name;}}
import java.lang.reflect.Field;
- public class PrivateTest {
- public static void main(String[] args) throws Exception{
- PrivateClass p = new PrivateClass();
- Class clazz = p.getClass();
- Field f = clazz.getDeclaredField("javaeye");
- f.setAccessible(true);//关键代码
- f.set(p,"lisi");
- System.out.println(p.getName());
- }
- }
public class PrivateTest {public static void main(String[] args) throws Exception{PrivateClass p = new PrivateClass();Class clazz = p.getClass();Field f = clazz.getDeclaredField("javaeye");f.setAccessible(true);//关键代码f.set(p,"lisi");System.out.println(p.getName());}}
上面这段代码表示将PrivateClass的name属性值改为javaeye,代码的关键在于:
- f.setAccessible(true);
f.setAccessible(true);
它表示可对私有的变量进行访问
3.数组的反射
- import java.lang.reflect.Array;
- /**
- * 数组反射测试
- * @author Administrator
- *
- */
- public class ArrayReflectTest1 {
- public static void main(String[] args) throws Exception{
- Class clazz = Class.forName("java.lang.String");
- Object arrObj = Array.newInstance(clazz,10);//得到数组的实例
- Array.set(arrObj,5,"zhangsan");//在数组第5个索引位置设置值zhangsan
- String res = (String)Array.get(arrObj,5);//得到第5个索引位置的值
- System.out.println(res);//打印此值
- }
- }
import java.lang.reflect.Array;/** * 数组反射测试 * @author Administrator * */public class ArrayReflectTest1 {public static void main(String[] args) throws Exception{Class clazz = Class.forName("java.lang.String");Object arrObj = Array.newInstance(clazz,10);//得到数组的实例Array.set(arrObj,5,"zhangsan");//在数组第5个索引位置设置值zhangsanString res = (String)Array.get(arrObj,5);//得到第5个索引位置的值System.out.println(res);//打印此值}}
4.多为数组的反射
- import java.lang.reflect.Array;
- /**
- * 多维数组的反射测试
- * @author Administrator
- *
- */
- public class ArrayReflectTest {
- public static void main(String[] args) {
- int[] i = new int[]{4,6,3};
- Object arr = Array.newInstance(Integer.TYPE,i);//得到的是一个三维数组
- Object arrObj = Array.get(arr,2);//此时得到的是一个二维数组
- arrObj = Array.get(arrObj,3);//此时得到的是一个一维数组
- Array.set(arrObj,2,21);
- int[][][] arrcast = (int[][][])arr;
- System.out.println(arrcast[2][3][2]);
- }
- }
import java.lang.reflect.Array;/** * 多维数组的反射测试 * @author Administrator * */public class ArrayReflectTest {public static void main(String[] args) {int[] i = new int[]{4,6,3};Object arr = Array.newInstance(Integer.TYPE,i);//得到的是一个三维数组Object arrObj = Array.get(arr,2);//此时得到的是一个二维数组arrObj = Array.get(arrObj,3);//此时得到的是一个一维数组Array.set(arrObj,2,21);int[][][] arrcast = (int[][][])arr;System.out.println(arrcast[2][3][2]);}}上述代码中,出现了Integer.TYPE,它不同于Integer.class.Integer.TYPE表示该包装类型对应的原始类型,如Integer对应与int. 今天继续学习了java反射
1.对象的拷贝功能
- class People {
- private Long id;
- private String name;
- private Integer age;
- public People() {
- }
- public People(Long id,String name,Integer age) {
- this.setId(id);
- this.setName(name);
- this.setAge(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;
- }
- public Integer getAge() {
- return age;
- }
- public void setAge(Integer age) {
- this.age = age;
- }
- }
class People { private Long id; private String name; private Integer age; public People() { } public People(Long id,String name,Integer age) { this.setId(id); this.setName(name); this.setAge(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; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } }
import java.lang.reflect.Constructor;
- import java.lang.reflect.Field;
- import java.lang.reflect.Method;
- public class ReflectTest3 {
- private static Object copy(Object obj) throws Exception {
- Class clazz = obj.getClass();
- Constructor cons = clazz.getConstructor(new Class[]{});//得到空的构造方法
- Object copyObj = cons.newInstance(new Object[]{});//间接调用空构造方法实例化copyObj
- Field[] fields = clazz.getDeclaredFields();//得到源对象的成员变量(该方法可得到私有的成员变量)
- for(Field field : fields) {
- String filedName = field.getName();
- //得到set、get方法
- String firstLetter = filedName.substring(0,1).toUpperCase();
- String getMethodName = "get"+firstLetter+filedName.substring(1);//得到get方法名称
- String setMethodName = "set"+firstLetter+filedName.substring(1);//得带get方法名称
- Method getMethod = clazz.getMethod(getMethodName,new Class[]{});
- Method setMethod = clazz.getMethod(setMethodName,field.getType());//得到set方法本身
- Object res = getMethod.invoke(obj,new Object[]{});//调用源对象的get方法
- setMethod.invoke(copyObj,res);
- }
- return copyObj;
- }
- public static void main(String[] args) throws Exception {
- People p = (People)copy(new People(1L,"张三",20));
- System.out.println(p.getId()+";"+p.getName()+";"+p.getAge());
- }
- }
import java.lang.reflect.Field; import java.lang.reflect.Method; public class ReflectTest3 { private static Object copy(Object obj) throws Exception { Class clazz = obj.getClass(); Constructor cons = clazz.getConstructor(new Class[]{});//得到空的构造方法 Object copyObj = cons.newInstance(new Object[]{});//间接调用空构造方法实例化copyObj Field[] fields = clazz.getDeclaredFields();//得到源对象的成员变量(该方法可得到私有的成员变量) for(Field field : fields) { String filedName = field.getName(); //得到set、get方法 String firstLetter = filedName.substring(0,1).toUpperCase(); String getMethodName = "get"+firstLetter+filedName.substring(1);//得到get方法名称 String setMethodName = "set"+firstLetter+filedName.substring(1);//得带get方法名称 Method getMethod = clazz.getMethod(getMethodName,new Class[]{}); Method setMethod = clazz.getMethod(setMethodName,field.getType());//得到set方法本身 Object res = getMethod.invoke(obj,new Object[]{});//调用源对象的get方法 setMethod.invoke(copyObj,res); } return copyObj; } public static void main(String[] args) throws Exception { People p = (People)copy(new People(1L,"张三",20)); System.out.println(p.getId()+";"+p.getName()+";"+p.getAge()); } }
用getConstructor方法时需要在类People中显示声明一个无参构造方法,尽管在Java中默认会隐式声明一个无参构造方法,
否则会抛出一个NoSuchMethod异常.getDeclaredFields方法可以得到private访问权限的成员变量,但只是只读的,不能
行修改,那怎样可以对私有属性的修改呢?
2.对私有属性的修改
- public class PrivateClass {
- private String name = "csdn";
- public String getName() {
- return this.name;
- }
- }
public class PrivateClass { private String name = "csdn"; public String getName() { return this.name; } }
import java.lang.reflect.Field;
- public class PrivateTest {
- public static void main(String[] args) throws Exception{
- PrivateClass p = new PrivateClass();
- Class clazz = p.getClass();
- Field f = clazz.getDeclaredField("javaeye");
- f.setAccessible(true);//关键代码
- f.set(p,"lisi");
- System.out.println(p.getName());
- }
- }
public class PrivateTest { public static void main(String[] args) throws Exception{ PrivateClass p = new PrivateClass(); Class clazz = p.getClass(); Field f = clazz.getDeclaredField("javaeye"); f.setAccessible(true);//关键代码 f.set(p,"lisi"); System.out.println(p.getName()); } }
上面这段代码表示将PrivateClass的name属性值改为javaeye,代码的关键在于:
- f.setAccessible(true);
f.setAccessible(true);
它表示可对私有的变量进行访问
3.数组的反射
- import java.lang.reflect.Array;
- /**
- * 数组反射测试
- * @author Administrator
- *
- */
- public class ArrayReflectTest1 {
- public static void main(String[] args) throws Exception{
- Class clazz = Class.forName("java.lang.String");
- Object arrObj = Array.newInstance(clazz,10);//得到数组的实例
- Array.set(arrObj,5,"zhangsan");//在数组第5个索引位置设置值zhangsan
- String res = (String)Array.get(arrObj,5);//得到第5个索引位置的值
- System.out.println(res);//打印此值
- }
- }
import java.lang.reflect.Array; /** * 数组反射测试 * @author Administrator * */ public class ArrayReflectTest1 { public static void main(String[] args) throws Exception{ Class clazz = Class.forName("java.lang.String"); Object arrObj = Array.newInstance(clazz,10);//得到数组的实例 Array.set(arrObj,5,"zhangsan");//在数组第5个索引位置设置值zhangsan String res = (String)Array.get(arrObj,5);//得到第5个索引位置的值 System.out.println(res);//打印此值 } }
4.多为数组的反射
- import java.lang.reflect.Array;
- /**
- * 多维数组的反射测试
- * @author Administrator
- *
- */
- public class ArrayReflectTest {
- public static void main(String[] args) {
- int[] i = new int[]{4,6,3};
- Object arr = Array.newInstance(Integer.TYPE,i);//得到的是一个三维数组
- Object arrObj = Array.get(arr,2);//此时得到的是一个二维数组
- arrObj = Array.get(arrObj,3);//此时得到的是一个一维数组
- Array.set(arrObj,2,21);
- int[][][] arrcast = (int[][][])arr;
- System.out.println(arrcast[2][3][2]);
- }
- }
import java.lang.reflect.Array; /** * 多维数组的反射测试 * @author Administrator * */ public class ArrayReflectTest { public static void main(String[] args) { int[] i = new int[]{4,6,3}; Object arr = Array.newInstance(Integer.TYPE,i);//得到的是一个三维数组 Object arrObj = Array.get(arr,2);//此时得到的是一个二维数组 arrObj = Array.get(arrObj,3);//此时得到的是一个一维数组 Array.set(arrObj,2,21); int[][][] arrcast = (int[][][])arr; System.out.println(arrcast[2][3][2]); } }上述代码中,出现了Integer.TYPE,它不同于Integer.class.Integer.TYPE表示该包装类型对应的原始类型,如Integer对应与int.