java基础review(4)---java反射

java反射

一、理论

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.

二、案例演示

/**
	 * 演示类
	 */
	public static class Person {
		static {
			System.out.println("静态代码块执行");
		}
		private Integer id;
		private String name;
		public Person(Integer id, String name) {
			super();
			this.id = id;
			this.name = name;
		}
		public Person() {
			super();
		}
		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 "Person [id=" + id + ", name=" + name + "]";
		}
		
	}

1、获取class对象的三个方式

	/**
	 * 	类.class
	 *  对象.getClass
	 *  Class.forName
	 */
	@Test
	public void test1() throws Exception {
		String className = "d18_reflect.review.ReflectDemo.Person";
		Class<?> clazz = Class.forName(className); // 方式1
		clazz = Person.class; // 方式2
		clazz = new Person().getClass(); // 方式3
 	}

2、class.forName() 三个参数以及自设类加载器候补顺序

	 * 自设定类加载器数组的顺序一般是:自设,Thread,本类,system。
	 * forName第二个参数如果为false,那么静态代码块不执行。
	 */
	@Test
	public void test2() throws Exception {
		String className = "d18_reflect.review.ReflectDemo$Person";
		ClassLoader cl = new ClassLoader[]{Thread.currentThread().getContextClassLoader(), getClass().getClassLoader(), 
				 ClassLoader.getSystemClassLoader()}[1];
		Class<?> clazz = Class.forName(className, true, cl);
		//  为false,静态代码块不执行
	}

 3、Method的反射

 * getDeclaredMethods : 本类的所有方法
	 * getMethods:本类的公开方法含父类
	 */
	@Test
	public void test3() throws Exception {
		Class<?> clazz = Person.class;
		Person person = (Person)clazz.newInstance();
		Method[] methods = clazz.getDeclaredMethods(); // 所有本类声明的方法
		for (Method method : methods) {
			System.out.println(method);
		}
		System.out.println("_______________");
		Method[] methods2 = clazz.getMethods(); //本类所有公开的方法
		for (Method method : methods2) {
			System.out.println(method);
		}
		Method method = clazz.getMethod("setName",new Class[]{String.class});
		System.out.println(method);
		Object object = method.invoke(person, "哈哈"); //方法执行
	}
	

 4、Field的反射

 * getDeclaredFields : 本类的声明字段
	 * getFields:全部公开字段
	 * setAccessible(true) 可访问公开字段
	 */
	@Test
	public void test4() throws Exception{
		Person demo = new Person();
		Class<?> clazz1 = Person.class;
		Field[] fields = clazz1.getFields();
		for (Field field : fields) {
			System.out.println("全部公开字段"+field.getName());
		}
		Field[] fields2 = clazz1.getDeclaredFields();
		for (Field field : fields2) {
			System.out.println("本类声明字段:"+field.getName());
		}
		//测试如何调用一个字段?
		Field declaredField = clazz1.getDeclaredField("name");                  
		declaredField.setAccessible(true); //暴力反射,私有字段采用
		declaredField.set(demo,"5");
		Object object = declaredField.get(demo);
		System.out.println(object.toString());
	}

5、数组的反射

    /**
	 * 5、数组的反射
	 * clazz.isArray() : 判断是数组
	 * Array.getLength : 数组长度
	 * Array.get(arr, 3):数组角标3的元素
	 */
	@Test
	public void test5() throws Exception{
		Object[] arr = new String[5];
		for (int i = 0; i < arr.length; i++) {
			arr[i] = i +"";
		}
		Class<?> class2 = arr.getClass();
		if(class2.isArray()){
			System.out.println(Array.getLength(arr));
			System.out.println(Array.get(arr, 3));
		}
	}

6、泛型反射

class Parent<T>{}

	class Student extends Parent<Object> {}
	
	class StudentExt extends Student{}
	
	/**
	 * 6、泛型反射
	 * getGenericSuperclass : 带泛型参数的父类
	 * ParameterizedType : type的子接口
	 * ParameterizedType.getActualTypeArguments : 真实类型参数的数组
	 */
	@Test
	public void test6() {
//		System.out.println(Object.class.getSuperclass()); //null
//		System.out.println(Student.class.getSuperclass());//class d18_reflect.review.ReflectDemo$Parent
//		System.out.println(Student.class.getGenericSuperclass());//d18_reflect.review.ReflectDemo$Parent<java.lang.Object>
		Class<?> clazz = findTtype(Person.class);
		System.out.println(clazz);
	}
	
	/**
	 * 父级泛型参数的类型查询-只支持2级查询
	 */
	public static Class<?> findTtype(Class<?> entity){
		Type type = entity.getGenericSuperclass(); // 带泛型参数的类型,class父接口
		if (!(type instanceof ParameterizedType)) { 
			type = entity.getSuperclass().getGenericSuperclass();
		}
		ParameterizedType parameterizedType = (ParameterizedType) type;
		Class entityClass = (Class) parameterizedType.getActualTypeArguments()[0];
		return entityClass;
	}
	
	/**
	 * 通过继承方式TypeReference类方式,获取子类传递的实际泛型参数
	 */
	abstract class TypeReference<T> {
		private final Type rawType;
		protected TypeReference() {
			rawType = getSuperclassTypeParameter(getClass());
		}
		Type getSuperclassTypeParameter(Class<?> clazz) {
			Type genericSuperclass = clazz.getGenericSuperclass();
			if (genericSuperclass instanceof Class) {
				if (TypeReference.class != genericSuperclass) {
					return getSuperclassTypeParameter(clazz.getSuperclass());
				}
			}
			Type rawType = ((ParameterizedType) genericSuperclass).getActualTypeArguments()[0];
			if (rawType instanceof ParameterizedType) {
				rawType = ((ParameterizedType) rawType).getRawType();
			}
			return rawType;
		}
		public final Type getRawType() {
			return rawType;
		}
	}

 

 

 

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值