Java 反射详解

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Luomingkui1109/article/details/79964347
1.为什么使用反射?
    我们都知道类用于描述现实生活中的一类事物,若需要描述某一个事物,通过 new 关键字, 创建其对象操作其属性,调用其方法。但在某种情况下,我们需要得知并使用一个在编译时完全未知的类,创建其对象,调用其属性和方法,这个时候就需要反射。
    反射机制(Reflection):反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
    Class 是开启反射的源头!

2.如何获取 Class 实例?
//1. 通过运行时类的属性 class
Class clazz = Person.class;

//2. 通过运行时类对象的 getClass() 方法
Person p = new Person();
Class clazz2 = p.getClass();

//3. 通过 Class 类中的静态方法  forName(String className)
String className = "com.meicai.collection.Person";
Class clazz3 = Class.forName(className);

//4. 通过类加载器(了解)
ClassLoader cl = this.getClass().getClassLoader();
Class clazz4 = cl.loadClass(className);
代码示例:
public class TestReflection {
     @Test
     public void test2() throws ClassNotFoundException{
         //1. 通过运行时类的属性 class
         Class clazz1 = Person.class;
         System.out.println("通过运行时类的属性 class :"+clazz1);

         //2. 通过运行时类对象的 getClass() 方法
         Person p = new Person();
         Class clazz2 = p.getClass();
         System.out.println("通过运行时类对象的 getClass() 方法:"+clazz2);

         //3. 通过Class类的静态方法 forName(String className)
         String className = "com.meicai.collection.Person";

         Class clazz3 = Class.forName(className);
         System.out.println("通过Class类的静态方法 forName(String className):"+clazz3);

         //4. 通过类加载器
         ClassLoader cl = this.getClass().getClassLoader();
         Class clazz4 = cl.loadClass(className);
         System.out.println("通过类加载器:"+clazz4);
     }
}
运行结果:
通过运行时类的属性 class :class com.meicai.collection.Person
通过运行时类对象的 getClass() 方法:class com.meicai.collection.Person
通过Class类的静态方法 forName(String className):class com.meicai.collection.Person
通过类加载器:class com.meicai.collection.Person
3.反射的功能
    ① 在运行时判断一个对象所属的类
    ② 在运行时创建任意一个类的对象
    ③ 在运行时判断一个对象的属性和方法
    ④ 在运行时调用一个对象的属性和方法
    ⑤ 生成动态代理

4.动态代理:
(1) 普通代理:
     说明:由于之前的普通代理会产生多个代理对象,煤老板一个代理对象,与钢铁老板一个代理对象,这样,我们能不能让一个代理去同时为多个老板代理业务呢?于是就有了我们下面的动态代理来解决这个问题。
(2) 动态代理:
public class SteelBoss implements Boss{

	@Override
	public void meet() {
		System.out.println("与钢铁老板见面");
	}

	@Override
	public void consume() {
		System.out.println("让钢铁老板消费");
	}

}
public class CoalBoss implements Boss{

	@Override
	public void meet() {
		System.out.println("与煤老板见面");
	}

	@Override
	public void consume() {
		System.out.println("让煤老板消费");
	}

}
/*
 * 动态代理(了解):需要实现接口 InvocationHandler
 * public Object invoke(Object proxy, Method method, Object[] args)
 * 
 * proxy : 动态生成的代理对象
 * method : 需要代理对象执行方法的 Method 的实例
 * args : 执行方法需要的参数
 */
public class DynaProxyHandler implements InvocationHandler{
	
	//目标对象
	private Object target;
	
	//生成动态代理对象
	public Object newProxyInstance(Object target){
		this.target = target;
		
		/*
		 * 第一个参数:通常与目标对象的类加载器保持一致!
		 * 
		 * 第二个参数:通常与目标对象实现的接口一致!
		 * 
		 * 第三个参数:需要实现了 InvocationHandler 接口实现类的实例。(目的,执行接口中的 invoke() 方法)
		 */
		return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
	}
	

	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		System.out.println("-----代理开始-----");
		
		Object obj = method.invoke(target, args);
		
		System.out.println("-----代理结束-----");
		return obj;
	}

}
public class SteelBoss implements Boss{

	@Override
	public void meet() {
		System.out.println("与钢铁老板见面");
	}

	@Override
	public void consume() {
		System.out.println("让钢铁老板消费");
	}

}
/*
 * 动态代理:
 */
public class TestProxy {
	
	public static void main(String[] args) {
		
		DynaProxyHandler dph = new DynaProxyHandler();
		
		Boss boss = (Boss) dph.newProxyInstance(new CoalBoss());
		boss.meet();
		boss.consume();
		
		System.out.println("-----------------------");
		Boss sb = (Boss) dph.newProxyInstance(new SteelBoss());
		sb.meet();
		sb.consume();
	}

}


阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页