继续来谈谈反射机制
- 要想使用反射,首先需要获得待处理类或对象所对应的Class对象。
 
2. 获取某个类或某个对象所对应的Class对象的常用的3种方式:
- 使用Class类的静态方法forName,Class.forName(“java.lang.String”);
 
- 使用类的.class语法:String.class;
 
- 使用对象的getClass()方法: String s=”aa”;Class<?> class=s.getClass();
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
   | import java.lang.reflect.Constructor;
  public class ReflactTester {
  	//该方法实现对Customer对象的拷贝操作 	public Object copy(Object object) throws Exception { 		Class<?> classType=object.getClass(); 		 //		System.out.println(classType.getName()); 		 		Constructor constructor = classType.getConstructor(new Class[] {}); 		 		Object object2= constructor.newInstance(new Object[] {}); 		 		 		 		//以上两行代码等价于下面一行 //		Object object2=classType.newInstance(); 		 //		 //		Constructor constructor3 = classType.getConstructor(new Class[] {String.class,int.class}); //		 //		Object object3= constructor3.newInstance(new Object[] {"hello",4}); 		 		 		System.out.println(object2); 	//	System.out.println(object3); 		 		return null;		 	} 	 	 	public static void main(String[] args) throws Exception { 		ReflactTester tester= new ReflactTester(); 		tester.copy(new Customer()); 	} } class Customer{ 	 	private Long id; 	 	private String name; 	 	private int age; 	 	public Customer() { 		 	} 	 	public Customer (String name, int age) { 		super(); 		this.name = name; 		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; 	}
  	public int getAge() { 		return age; 	}
  	public void setAge(int age) { 		this.age = age; 	}
  }
   | 
 
运行结果:
3.若想通过类的不带参数的构造方法来生成对象,我们有两种方式:
4.若想通过类的带参数的构造方法生成对象,只能使用下面这一种方式:
1 2 3
   | Class<?> classType = Customer.class;  Constructor cons = classType.getConstructor(new Class[]{String.class, int.class});  Object obj = cons.newInstance(new Object[]{“hello”, 3});
   | 
 
我们再来看一个例子,ReflectTester类有一个 copy(Object object)方法,这个方法能够创建 一个和参数object 同样类型的对象,然后把 object对象中的所有属性拷贝到新建的对象中, 并将它返回
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
   | import java.lang.reflect.Field; import java.lang.reflect.Method;
  public class ReflactTester2 {
  	public Object copy(Object object )throws Exception {     	//获得对象的类型 		Class<?> classType = object.getClass(); 		//System.out.println("Class:"+classType.getName()); 		 		//通过无参数的构造方法构造出来类并且实例化 		Object objectCopy=classType.getConstructor(new Class[] {}).newInstance(new Object[] {}); 		 		//获得对象的所有成员变量 		 		Field[] fields= classType.getDeclaredFields(); 		 		for(Field field:fields) { 			//获得属性的名称 			String name=field.getName(); 			 			//变量名称首字母大写 			String firstLetter=name.substring(0,1).toUpperCase(); 			 			//获取到get、set方法的名称 			String getMethodName="get"+firstLetter+name.substring(1); 			String setMethodName="set"+firstLetter+name.substring(1); 			 			//获取到get、set方法 			Method getMethod=classType.getMethod(getMethodName, new Class[] {}); 			Method setMethod=classType.getMethod(setMethodName, new Class[] {field.getType()}); 			 			//set方法没有参数 			Object value=getMethod.invoke(object, new Object[] {}); 			 			//将get到的属性值传入 			setMethod.invoke(objectCopy, new Object[] {value}); 		}	 			return objectCopy;	 	} 	 	public static void main(String[] args) throws Exception{ 		Customer customer = new Customer("Tom",20); 		//注意是long类型的哟 		customer.setId(1L); 		 		ReflactTester tester = new ReflactTester(); 		 		Customer customer2 = (Customer) tester.copy(customer); 		 		//System.out.println(customer2.getId()+","+customer2.getName()+","+customer2.getAge()); 	} 	 	 }
   | 
 
运行结果显示:
Class类是Reflection API 中的核心类,它有以下方法 :
getName():获得类的完整名字。
 
getFields():获得类的public类型的属性。
 
getDeclaredFields():获得类的所有属性。
 
getMethods():获得类的public类型的方法。
 
getDeclaredMethods():获得类的所有方法。
Method类的invoke(Object obj,Object args[])方法接 收的参数必须为对象,如果参数为基本类型数据,必须转 换为相应的包装类型的对象。invoke()方法的返回值总是 对象,如果实际被调用的方法的返回类型是基本类型数据 ,那么invoke()方法会把它转换为相应的包装类型的对象 ,再将其返回.
 
下面我们来看看数组,java.lang.Array 类提供了动态创建和访 问数组元素的各种静态方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
   | import java.lang.reflect.Array;
  public class ArrayTester1 { 	public static void main(String[] args) throws Exception 	{ 		Class<?> classType = Class.forName("java.lang.String"); 		 		Object array = Array.newInstance(classType, 10); 		 		Array.set(array, 5, "hello"); 		 		String str = (String)Array.get(array, 5); 		 		System.out.println(str); 	} }
   | 
 
运行结果:
hello
创建 了一个 5 x 10 x 15 的整型数组,并把索 引位置为[3][5][10] 的元素的值为设37
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
   | import java.lang.reflect.Array;
  public class ArrayTester2 { 	public static void main(String[] args) 	{ 		int[] dims = new int[] { 5, 10, 15 };
  		Object array = Array.newInstance(Integer.TYPE, dims); 		 		System.out.println(array instanceof int[][][]);
  //二维数组 		Object arrayObj = Array.get(array, 3);
  //Class<?> classType=arrayObj.getClass().getComponentType(); //System.out.println(classType);
  //一维数组 		arrayObj = Array.get(arrayObj, 5);
 
  		Array.setInt(arrayObj, 10, 37);
  		int[][][] arrayCast = (int[][][]) array;
  		System.out.println(arrayCast[3][5][10]);
  		// System.out.println(Integer.TYPE); 		// System.out.println(Integer.class);
  	} }
   | 
 
- Integer.TYPE 返回的是 int,而 Integer.class 返回的是 Integer 类所对应的 Class 对象。
 
反射破坏了类的封装性,可以调用私有的方法,变量,接下来我们一起来看看
1 2 3 4 5 6
   | public class PivateTest {
  	private String sayHello(String name) { 		return "hello"+name; 	} }
  | 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
   | import java.lang.reflect.Method;
  public class Private {
  	public static void main(String[] args) throws Exception { 		 		PivateTest private1 = new PivateTest(); 		 		Class<?> classType=private1.getClass(); 		 		 		 	    Method  method = classType.getDeclaredMethod("sayHello", new Class[] {String.class}); 		 		method.setAccessible(true);//压制java的访问权限的内部检查 	 		String string = (String)method.invoke(private1, new Object[] {"  zhangsan"}); 		 		System.out.println(string); 	} }
   | 
 
运行结果:
用反射更改私有的成员变量的值,怎么实现呢,我们来看看
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
   | import java.lang.reflect.Field;
  public class Private2 {
  	 	private String name="zhangsan"; 	 	public String getName() { 		return name; 	} 	 	public static void main(String[] args) throws Exception{ 		 		Private2 private2 = new Private2(); 		 		Class<?> classType=Private.class; 		 		Field field=classType.getDeclaredField("name"); 		 		//压制java对访问修饰符的检查 		field.setAccessible(true); 		 		//对于属性的操作,直接使用get或是set方法就可以了 		field.set(private2, "lisi"); 	 		System.out.println(private2.getName()); 		 	} 	 }
   | 
 
运行后的结果:
众所周知Java有个Object class,是所有 Java classes的继承根源,其内声明了数 个应该在所有Java class中被改写的 methods:hashCode()、equals()、 clone()、toString()、getClass()等。其 中getClass()返回一个Class object。
- Class class十分特殊。它和一般classes一样继承自 Object,其实体用以表达Java程序运行时的classes和 interfaces,也用来表达enum、array、primitive Java types
 
- (boolean, byte, char, short, int, long, float, double)以及关键词void。当一个class被加载,或当加 载器(class loader)的defineClass()被JVM调用, JVM 便自动产生一个Class object。如果您想借由“修 改Java标准库源码”来观察Class object的实际生成时 机(例如在Class的constructor内添加一个println()) ,不能够!因为Class并没有public constructor
只有java虚拟机可以创建一个Class 
- Class是Reflection起源。针对任何您想探 勘的class,唯有先为它产生一个Class object,接下来才能经由后者唤起为数十 多个的Reflection APIs
 
为什么获得Method object时不需指定回返类型?
- 因为method overloading机制要求 signature必须唯一,而回返类型并非 signature的一个成份。换句话说,只要指定了method名称和参数列,就一定指出了 一个独一无二的method。(在方法重载的那个地方也是这样)
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
   | public class ClassTest {
  	public static void main(String[] args) 	{ 		Class<?> classType = Child.class; 		 		System.out.println(classType); 		 		classType = classType.getSuperclass(); 		 		System.out.println(classType); 		 		classType = classType.getSuperclass(); 		 		System.out.println(classType); 		 		classType = classType.getSuperclass(); 		 		System.out.println(classType); 	} 	 } class Parent{ 	 } class Child extends Parent { 	 }
  | 
 
运行结果:
1 2 3 4
   | class Child class Parent class java.lang.Object null
   | 
 
什么时候能用到反射呢?
实际开发中一般是用不到反射的,除非自己去写框架肯定会用到反射,掌握了反射机制,对于以后学框架有利,理解更深入。
我的csdn博客