反射(Reflection)

反射所对应的包

Class类位于java.lang包下,在java中反射所用到的包位于java.lang.reflect包下:

  1. Class类:代表一个类
  2. Field类:代表类的属性
  3. Method类:代表类的方法
  4. Constructor类:代表类的构造方法

反射的步骤

要想使用反射,第一步都需要获得该类或者对象所对应的Class对象。

注意:在java中无论一个类生成了多少个实例,这些实例都对应了唯一一个Class对象。

  1. 获得对应的Class对象有三种方式:
    • 使用Class类的静态方法forName(),例如:Class clazz = Class.forName("java.lang.String");
    • 使用类的class,例如:Class clazz = String.class;
    • 使用对象的getClass()方法:
      String str = "hello world";
      Class clazz = str.getClass();

例子

public class InvokerTest
{
	public int add(int a,int b)
	{
		return a + b;
	}
	
	public String say(String str)
	{
		return "Hello: " + str;
	}
}


使用反射调用方法:

public static void main(String[] args) throws Exception
	{
		//反射获取class对象
		Class clazz = Class.forName("com.zhkj.reflect.InvokerTest");//Class clazz = InvokerTest.class;
		
		//通过class对象获取实例
		Object obj = clazz.newInstance();
		
		//通过class对象获取某个方法,第一个参数为方法名,第二个参数为方法所接受的参数的class对象。
		Method method = clazz.getMethod("add",new Class[] {int.class,int.class});
		
		//通过method调用方法并传递参数,第一个参数为调用该方法的对象,第二个参数为方法的实际参数
		Object result = method.invoke(obj,new Object[] {3,4});
		
		System.out.println(result);
		
		//获取方法名
		Method[] methods = clazz.getDeclaredMethods();
		
		for(Method m : methods)
		{
			System.out.println(m);
		}
	}

Class类、Method类及Field类的使用

先获得Class对象,然后通过该对象获得对应的Constructor对象,再通过该Constructor对象的newInstance()方法生成:
Customer对象
public class Customer
{
	private Long id;
	
	private String name;
	
	private int age;
	
	public Customer()
	{
		
	}
	
	public Customer(String name,int age)
	{
		this.name = name;
		
		this.age = age;
	}
}



创建Customer对象的实例:
Class<?> clazz = Customer.class;
Constructor cons = clazz.getConstructor(new Class[] {String.class,int.class});
Object obj = cons.newInstance(new Object[] {"hello",3});
实现Customer类的拷贝:
//该方法实现Customer的拷贝
	public Object copy(Object oldObject) throws Exception
	{
		//获取Class类
		Class<?> clazz = oldObject.getClass();
		
		//创建实例
		Object newObject = clazz.getConstructor(new Class[]{}).newInstance(new Object[]{});
		
		//获取属性数组
		Field[] fieldArray = clazz.getDeclaredFields();
		
		//遍历得到每个属性
		for(Field field : fieldArray)
		{
			//得到属性名
			String name = field.getName();
			
			//获取首字母,将其转换为大写
			String firstLetter = name.substring(0,1).toUpperCase();
			
			//拼接get方法名
			String getMethodName = "get" + firstLetter + name.substring(1);
			
			//获取get方法
			Method getMethod = clazz.getMethod(getMethodName,new Class[]{});
			
			//拼接set方法名
			String setMethodName = "set" + firstLetter + name.substring(1);
			
			//获取set方法
			Method setMethod = clazz.getMethod(setMethodName,new Class[]{field.getType()});
			
			//调用get方法获取值
			Object value = getMethod.invoke(oldObject,new Object[]{});
			
			//调用set方法
			setMethod.invoke(newObject,new Object[]{value});
			
		}
		
		return newObject;
	}

Integer.TYPE返回的是int,而Integer.class返回的是Integer类所对应的Class对象。



你可能感兴趣的:(java,反射,reflection)