java basic review(4)---java reflection

java reflection

1. Theory

JAVA reflection mechanism is in the running state, for any class, you can know all the properties and methods of this class; for any object, you can call any of its methods and properties; this kind of dynamically acquired information and dynamic calls The function of the method of the object is called the reflection mechanism of the java language.

If you want to dissect a class, you must first obtain the bytecode file object of the class. The anatomy uses the methods in the Class class. Therefore, first obtain the Class type object corresponding to each bytecode file.

2. Case demonstration

/**
	 * 演示类
	 */
	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. Three ways to obtain class objects

	/**
	 * 	类.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. The three parameters of class.forName() and the alternate order of the custom class loader

	 * 自设定类加载器数组的顺序一般是:自设,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 reflection

 * 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 reflection

 * 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. Array reflection

    /**
	 * 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. Generic reflection

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;
		}
	}

 

 

 

 

Guess you like

Origin blog.csdn.net/shuixiou1/article/details/112591588