原创

Java 基础之反射机制详解

        JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。即为 在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。


功能清单1

1)获取对象包名称和类名称

2)所有类的对象其实都是Class的实例

3)通过Class实例化其他类的对象

4)获取类的所有实现接口

5)获取类的继承父类

6)获得其他类中的全部构造函数以及通过Class调用其他类中的构造函数

7)获取得其他类的全部属性,通过class取得一个类的全部框架

8)通过反射调用其他类中的方法

9)调用其他类的set和get方法

10)通过反射操作属性

11)获得类加载器,AppClassLoader 加载classpath指定的类,是最常用的加载器,也是java中默认的加载器。

        为了方便运行,所有函数写在一个测试类中,具体代码注释以及运行结果都有包含(大家感觉有帮助帮忙转载一下,有什么问题文章下留言评论),具体代码如下文:

package com.yoodb;

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

public class TestMain {
	
	public static void main(String[] args) {
		Demo demo = new Demo();
		Class<?> demoAll = null;
		try {
			demoAll = Class.forName("com.yoodb.Demo");
		} catch (ClassNotFoundException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		/********** 获取对象包名称和类名称  **********/
		System.out.println(demo.getClass().getName());
		//输出结果: com.yoodb.Demo
		
		/********** 所有类的对象其实都是Class的实例  **********/
		Class<?> demo1 = null;
		Class<?> demo2 = null;
		Class<?> demo3 = null;
		try {
			demo1 = new Demo().getClass();
			demo2 = Demo.class;
			demo3 = Class.forName("com.yoodb.Demo");
			System.out.println("demo1==>" + demo1);
			System.out.println("demo2==>" +demo2);
			System.out.println("demo3==>" +demo3);
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		/* 输出结果:
		   demo1==>class com.yoodb.Demo
		   demo2==>class com.yoodb.Demo
		   demo3==>class com.yoodb.Demo
		 */
		
		/********** 通过Class实例化其他类的对象  **********/
		try {
			demo = (Demo) demoAll.newInstance();
			demo.setId(1);
			demo.setName("www.yoodb.com");
			System.out.println("DEMO 对象==>" + demo);
		} catch (InstantiationException | IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		//输出结果: DEMO 对象==>Demo [id=1, name=www.yoodb.com]
		
		/********** 获取类的所有实现接口  **********/
		Class<?>[] tfs = demoAll.getInterfaces();
		for (Class<?> cla : tfs) {
			System.out.println("DEMO 对象 实现接口==>" + cla.getName());
		}
		//输出结果:DEMO 对象 实现接口==>com.yoodb.TFDemo
		
		/********** 获取类的继承父类  **********/
		Class<?> sc = demoAll.getSuperclass();
		System.out.println("DEMO 对象 继承父类==>" + sc.getName());
		//输出结果:DEMO 对象 继承父类==>com.yoodb.FTDemo
		
		/********** 获得其他类中的全部构造函数以及通过Class调用其他类中的构造函数  **********/
		Constructor<?>[] cts = demoAll.getConstructors();
		try {
			for (Constructor<?> ctr : cts) {
				System.out.println("构造函数 ==>" + ctr);
			}
			demo = (Demo) cts[1].newInstance(1,"www.yoodb.com");//注意有参无参构造方法的先后顺序
			System.out.println("调用其他类构造函数 ==>" + demo);
		} catch (InstantiationException | IllegalAccessException
				| IllegalArgumentException | InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		/* 输出结果:
			构造函数 ==>public com.yoodb.Demo()
			构造函数 ==>public com.yoodb.Demo(java.lang.Integer,java.lang.String)
			调用其他类构造函数 ==>Demo [id=1, name=www.yoodb.com]
		 */
		
		/********** 获取得其他类的全部属性,通过class取得一个类的全部框架  **********/
		Field[] fields = demoAll.getDeclaredFields();
		for (Field field : fields) {
			int mfs = field.getModifiers();
			String priv = Modifier.toString(mfs);
			Class<?> type = field.getType();
			System.out.println("权限修饰符==>" + priv);
			System.out.println("属性类型==>" + type);
			System.out.println("属性名称==>" + field.getName());
		}
		/* 输出结果:
			 权限修饰符==>private
			属性类型==>class java.lang.Integer
			属性名称==>id
			权限修饰符==>private
			属性类型==>class java.lang.String
			属性名称==>name
		 */
		
		/********** 通过反射调用其他类中的方法  **********/
		try {
			Method method = demoAll.getMethod("execte",Integer.class,String.class);
			method.invoke(demoAll.newInstance(), 20 , "中国");
		} catch (NoSuchMethodException | SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException | IllegalArgumentException
				| InvocationTargetException | InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		// 输出结果:集合==>20---中国
		
		/********** 调用其他类的set和get方法  **********/
		try {
			Object obj = demoAll.newInstance();
			setter(obj, "Id" ,20, Integer.class);
			getter(obj,"Id");
		} catch (InstantiationException | IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		//输出结果==> get 方法输出==>20
		
		/********** 通过反射操作属性  **********/
		try {
			Object obj = demoAll.newInstance();
			Field field = demoAll.getDeclaredField("name");
			field.setAccessible(true);
			field.set(obj, "www.yoodb.com");
			System.out.println(field.get(obj));
		} catch (InstantiationException | IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchFieldException | SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		//输出结果:www.yoodb.com
		
		
		/********** 获得类加载器  **********/
		System.out.println("类加载器==>"+ demo.getClass().getClassLoader().getClass().getName());
		// 输出结果:类加载器==>sun.misc.Launcher$AppClassLoader
	}
	
	/**
	 * @param obj 操作对象
	 * @param att 操作属性名称
	 */
	private static void getter(Object obj,String att){
		try {
			Method method = obj.getClass().getMethod("get" + att);
			System.out.println("get 方法输出==>" + method.invoke(obj));
		} catch (NoSuchMethodException | SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException | IllegalArgumentException
				| InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	/**
	 * @param obj 操作对象
	 * @param att 操作属性名称
	 * @param value 设置值
	 * @param type 参数属性
	 */
	private static void setter(Object obj, String att, Object value, Class<?> type){
		try {
			Method method = obj.getClass().getMethod("set" + att, type);
			method.invoke(obj, value);
		} catch (NoSuchMethodException | SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException | IllegalArgumentException
				| InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

辅助测试类,包含继承类,接口以及数据类,具体代码如下:

package com.yoodb;

//继承类
class FTDemo {

}
//实现接口
interface TFDemo {

}

public class Demo extends FTDemo implements TFDemo{
	private Integer id;
	
	private String name;
	
	public Demo() {
	}

	public Demo(Integer id, String name) {
		this.id = id;
		this.name = name;
	}
	
	public void execte(Integer id,String name){
		System.out.println( "集合==>" + id + "---" + name );
	}

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Override
	public String toString() {
		return "Demo [id=" + id + ", name=" + name + "]";
	}
	
	
}

所有输出结果如下:

com.yoodb.Demo
demo1==>class com.yoodb.Demo
demo2==>class com.yoodb.Demo
demo3==>class com.yoodb.Demo
DEMO 对象==>Demo [id=1, name=www.yoodb.com]
DEMO 对象 实现接口==>com.yoodb.TFDemo
DEMO 对象 继承父类==>com.yoodb.FTDemo
构造函数 ==>public com.yoodb.Demo()
构造函数 ==>public com.yoodb.Demo(java.lang.Integer,java.lang.String)
调用其他类构造函数 ==>Demo [id=1, name=www.yoodb.com]
权限修饰符==>private
属性类型==>class java.lang.Integer
属性名称==>id
权限修饰符==>private
属性类型==>class java.lang.String
属性名称==>name
集合==>20---中国
get 方法输出==>20
www.yoodb.com
类加载器==>sun.misc.Launcher$AppClassLoader


功能清单2

将反射应用于工厂模式,方便于在添加每个子类的时候不用去修改工厂类

工厂模式不是很了解的话,建议看一下“ Java 设计模式之工厂模式 文章 ”,链接地址:http://blog.yoodb.com/yoodb/article/detail/309

将反射用于工厂模式,具体代码如下文:

package com.yoodb;

public class FactoryMode {
	public static void main(String[] args) {
		Animal fy = Factory.getInstance("com.yoodb.Cat");
		if(fy != null){
			fy.eat();
		}
	}
}

interface Animal{
	public void eat(); 
}

class Cat implements Animal{
	public void eat(){
		System.out.println("猫吃鱼!");
	}
}

class Dog implements Animal{
	public void eat(){
		System.out.println("狗吃肉!");
	}
}

class Factory {
	public static Animal getInstance(String className){
		Animal al = null;
		try {
			al = (Animal) Class.forName(className).newInstance();
		} catch (InstantiationException | IllegalAccessException
				| ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return al;
	}
}


功能清单3

利用反射机制将 JavaBean 复制给另一个JavaBean 对象,具体代码如下文:

package com.yoodb;

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

public class Reflect {
	
	public static void main(String[] args) {
		Deer deer = new Deer();
		deer.setId(1);
		deer.setName("www.yoodb.com");
		Deer et = (Deer) invoke(deer);
		System.out.println(et);
		// 输出结果:Deer [id=1, name=www.yoodb.com]
	}
	
	public static Object invoke(Object object){
		Object newObj = null;
		try {
			Class<?> cla = object.getClass();
			newObj = cla.getConstructor(new Class[]{}).newInstance(new Object[]{});
			Field[] fields = object.getClass().getDeclaredFields();
			for (Field field : fields) {
				String fieldName = field.getName();
				String firstLetter = fieldName.substring(0,1).toUpperCase();
				String getMethodName = "get" + firstLetter + fieldName.substring(1);//对象里所有get*函数
				String setMethodName = "set" + firstLetter + fieldName.substring(1);//对象里所有set*函数
				Method getMethod = cla.getMethod(getMethodName, new Class[]{});
				Method setMethod = cla.getMethod(setMethodName, new Class[]{field.getType()});
				//调用原对象中的get*函数
				Object value = getMethod.invoke(object, new Object[]{});
				//调用复制对象set*函数
				setMethod.invoke(newObj, new Object[]{value});
			}
		} catch (InstantiationException | IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchMethodException | SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException | InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return newObj;
	}
}

class Deer{
	private Integer id;
	
	private String name;
	
	public Deer() {}

	public Deer(Integer id, String name) {
		this.id = id;
		this.name = name;
	}

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Override
	public String toString() {
		return "Deer [id=" + id + ", name=" + name + "]";
	}

}

复制一个类的对象,为newObj,程序中的 new Class[]{} 是一种快捷方式,获得方法的引用。[]中用来放参数,{}里面可以放置方法的返回类型。new Class[]{}相当于new class("构造函数参数").newinstance(),输出结果如下:

Deer [id=1, name=www.yoodb.com]

关注下方微信公众号“Java精选”(w_z90110),回复关键字领取资料:如HadoopDubboCAS源码等等,免费领取资料视频和项目。 

涵盖:程序人生、搞笑视频、算法与数据结构、黑客技术与网络安全、前端开发、Java、Python、Redis缓存、Spring源码、各大主流框架、Web开发、大数据技术、Storm、Hadoop、MapReduce、Spark、elasticsearch、单点登录统一认证、分布式框架、集群、安卓开发、iOS开发、C/C++、.NET、Linux、Mysql、Oracle、NoSQL非关系型数据库、运维等。

评论

分享:

支付宝

微信