Java反射机制

      一直以来,不论是C#还是java,反射都是一个非常实用的技术。因为有了反射,在数据库的切换上更加得容易;因为有了反射,一些本不肯能的事情,成为了现实;因为有了反射,在java中,才有了那么多经典的框架……
      在此,跟大家分享一下自己的一些比较粗浅的认识,希望能给刚开始学习的你,带来一丁点帮助。
      在说反射之前,首先要搞懂几个比较专业的概念:
1.在java中,每一个类都有一个与之对应的class对象。而且不论该类的实例化了多少个对象,都只有一个Class对象与之对应。
2.java里每一个类里的每一个方法都会有一个与之对应的method方法,如果要通过反射调用该方法,就需先获得该方法对应的method对象,然后通过调用method方法去访问其所代表的方法。这个method对象可以获取方法的所有属性和方法(不包括方法体,即方法的实现)。
3. java中,每个属性对应一个field对象。
4.在java中,只要通过方法的名称和参数列表即确定一个方法,和返回值没有太多的关系。
5. java中,每个类的构造方法对应一个Constructor对象。
     正是由于以上的5个对象,才使得反射成了可能。反射的实现原理大致总结如下:获取类的Class对象clazz,然后通过clazz对象,获取实例对象(Constructor)和对象中的方法(Method)及属性(Field)。然后通过Method对象就可以访问该clazz对象中的方法,进行一些业务的操作。

    给出一张不太贴切的图:


获取Class对象的方式:
1.getClass方式
通过某个类的实例的getClass方式可获得该类对应的Class对象
2. getSuperclass方式
通过子类的Class对象的getSuperclass方法获取父类对应的的Class对象
3.forName方式(常用)
通过Class类的【forName(String “类的全名”)】方法获取对应的Class对象
4.*.class方式
通过 类.class 方式获取其对应的Class对象


5.对于包装数据类型,通过TYPE来获取对应的Class对象


获取类的实例对象的方式有两种:
1.无参数构造函数类
对于无参数的构造函数,在获取类的实例对象的时候,可以直接使用Class对象的newInstance方法获取。



2.有参数构造函数
如果目标类的构造函数有参数,则需要调用getConstructor方法获取Constructor对象(前面说过了,类的构造函数对应Constructor对象)实例。然后通过该实例来创建目标类的实例对象。



       其实,无参数构造函数是有参数构造函数的一个特例,所以,有参数的构造函数的生成目标类实例对象的方法同样适用于无参数的。
下面给出几个实现的Demo

Demo 一、

package com.test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class DumpMethod {

	//从命令行接受一个字符串(该字符串是某个类的全名)
	//打印出该类中的所有方法声明
	public static void main(String[] args) throws Exception {
		
		//Class类是java反射的入口点
		Class classtype=Class.forName("com.test.people");
		
		System.out.println(classtype);
		
		Method[] methods=classtype.getDeclaredMethods();
		
		Constructor<?> con=classtype.getConstructor();
		
		Object ob=con.newInstance();
		
	
		for(Method method:methods){
			//System.out.println(method);
			if (method.getName().equals("setPeople")) {
				String o=(String) method.invoke(ob);
				System.out.println(o);
			}
		}

	}
}

class people{
	
	public people(){}
	
	private int count;
	
	public String setPeople(){
		return "I am cool";
	}
}

Demo 二

package com.test;

import java.lang.reflect.Method;

public class InvokeTester {

	public int add(int a,int b){
		return a+b;
	}
	
	public String echo(String msg){
		return msg;
	}
	

	public static void main(String[] args) throws Exception {
		
		 //会获得InvokeTester类所对应的Class对象
		Class<?> classType=InvokeTester.class;
		
		//newInstance会获得classType所对应的类的实例,该类必须有一个无参数的构造方法
		Object invokerObject=classType.newInstance();
		//********以上两行代码等价于下边的一行代码:
		//InvokeTester i=new InvokeTester();
		
		
		//java里每一个类里的每一个方法都会有一个与之对应的method方法,
		//如果要通过反射调用该方法,就需要调用method方法
		
		Method addMethod=classType.getMethod("add", new Class[]{int.class,int.class});
		
		Object result=addMethod.invoke(invokerObject, new Object[]{100,200});
		
		//以上两行代码等价于 i.add(100,200)
		
		System.out.println(result);
		System.out.println(int.class);
		

	}
}

Demo 三、

package com.test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;


public class ReflecTester {

	public Object copy(Object object) throws Exception{
	
		Class<?> classType=object.getClass();
		
		//classType
		//System.out.println(classType.getName());
		
		//会获得该类里不带参数的构造方法所对应的Constructor对象
		//等价于
		//Object objectCopt2=classType.newInstance();
		//这种等价的方式只能生成不带参数的构造函数实例,如果带参数,则无法使用了
		Constructor<?> con=classType.getConstructor(new Class[]{String.class});
		
		Object obje=con.newInstance(new Object[]{"This is a demo"});
		
		Object objectCopy=classType.getConstructor(new Class[]{})
				.newInstance(new Object[]{});
		
		//获得对象所有属性,用于拼接方法,然后使用
		Field[] fields=classType.getDeclaredFields();
		
		
		for(int i=0;i<fields.length;++i){
			
			Field field=fields[i];
			//获取属性名
			String a=field.getName();
			
			//获得属性的首字母并且转化为大写
			String firstLetter=a.substring(0,1).toUpperCase();
			
			//获得和属性对应 的getXX()方法的名字
			String getMethodName="get"+firstLetter+a.substring(1);
			
			//获得和属性对应 的setXX()方法的名字
			String setMethodName="set"+firstLetter+a.substring(1);
			
			//通过拼接的方法名获取对应的Method对象
			Method getMethod=classType.getMethod(getMethodName, new Class[]{});
			
			Method setMethod=classType.getMethod(setMethodName, 
					new Class[]{field.getType()});
			
			//获取方法的值
			Object value=getMethod.invoke(object, new Object[]{});
			
			System.out.println(a+":"+value);
			
			setMethod.invoke(objectCopy, new Object[]{value});
	
		}
			
		return objectCopy; 
		
		
	}
	
	
	public static void main(String[] args) throws Exception {
		
		
		Customer customer=new Customer();
		customer.setId(new Long(1));
		customer.setName("LCY");
		customer.setAge(20);
		
		Customer customerCopy= (Customer)new ReflecTester().copy(customer);
		
		
		System.out.println(customerCopy.getName()+","+customerCopy.getAge());
		
	}
	
	
	
}

class Customer{
	
	public Customer(){}
	
	public Customer(String name){
		
	}
	private  Long id;
	
	private String name;
	
	private int 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;
	}
	
	
}



评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值