[Lehr] Java reflection basics

Class class

What is the class Class

With the Java核心技术卷official words of it:
during program execution, the runtime system for all Java objects always maintain type identifier is known as a run-time, this tracking information for each object belongs to a class, virtual machine using the run-time type information select the appropriate method is executed. Our child in programming can be accessed by using special Java classes, class save this information is called Class.

Simply put, it is this:
In Java, there is a class specifically to describe the class itself, which is the Class class that can describe what a Java class interfaces, constructors, methods, class names, attributes and so on.

Class class can only be created by the JVM. And each Java class corresponds to only a Class instance, which is stored inside on this feature of the Java class: What interfaces, what parent class is, what method to wait.

In all the following examples, we need to use a class called Person, as follows:

public class Person {

	//有名字和年龄
	private String name;
	private int age;
	
	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;
	}
	//无参构造器
	public Person(){}
	//有参构造器
	public Person(String name, int age) {
		this.name = name;
		this.age = age;
	}
	//一个私有方法
	private void secretMethod(){}
	
}

How to use the Class class

Get to the JVM already created Class class has three methods:

1. Using class acquired

	Class clazz1 = Person.class;

2. Use the full name of the class acquired

	Class clazz2 = Class.forName("com.reflection.Person");

3. Use Example to obtain

	Class clazz3 = person.getClass();

This method is often used for objects you do not know this particular case is what kind of, for example:

	//这里只是举例,如果从外部传入就不一定知道是Person类了
	Object person = new Person();
	Class clazz2 = person.getClass();
	System.out.println(clazz3);

Output: the right to obtain a specific class
Here Insert Picture Description
and now you've got, this is called clazz object is a type Class, store the object information Person of this class, you can use clazz, operating by reflection, view and modify properties and methods of the Person class.

Next, we can first use this clazz object to create an instance of the object of the Person!
Using the newInstance()method:

	Object obj = clazz1.newInstance();
	System.out.println(obj);

Output:
Here Insert Picture Description
obj is a Person class, successfully created!
It should be note, newInstance()the method is in fact the Person class, no arguments constructor calls, so if there are no write-Person class constructor with no parameters, it will fail here.

Java JVM will only give each class to create a Class instance, we can compare just get three kinds of objects Class way to get the address to verify this:

	System.out.println(clazz1==clazz2);
	System.out.println(clazz2==clazz3);	

Output:
Here Insert Picture Description

Three Loader

Class loader (ClassLoader), the class is loaded into the JVM used. When the JVM starts, Java will be in the following order from top to bottom starting three categories loader and load the appropriate class, and they in turn were inheritance:

1. bootstrap class loader (Bootstrap): written in C ++, is a native JVM class loader is responsible for responsible for the Java platform Java core libraries,Core classes for loading(Such as the Object class, String, etc.). Since the bootstrap class loader relates to a local virtual machine implementation details, it does not allow direct manipulation by reference,Can not be accessed directly

2. The extension class loader (Extension):
由Sun的ExtClassLoader(sun.misc.Launcher$ExtClassLoader)实现的
responsible for loading <JAVA_HOME> / lib / ext or specified by the system variable position -Djava.ext.dir library into memory. Developers can directly use the standard extensions class loader.

3. The system class loader (System):
由 Sun 的 AppClassLoader(sun.misc.Launcher$AppClassLoader)实现的
TheUser-written classLoaded into memory. Developers can directly use the system class loader.

With code validation inheritance:


		//获取系统类加载器
		ClassLoader classLoader = ClassLoader.getSystemClassLoader();
		System.out.println(classLoader);
		
		//获取系统类加载器的父类----扩展类加载器
		System.out.println(classLoader.getParent());
		
		//获取扩展类加载器的父类----引导类加载器
		System.out.println(classLoader.getParent().getParent());		

Output Results:
Here Insert Picture Description
The last is output nullbecause the boot class loader can not be accessed directly.

What now then try to verify what type loader to load:

	//测试自己写的类是哪个加载器加载的
	System.out.println(Person.class.getClassLoader());
		
	//测试JDK提供的类由哪个加载器负责
	System.out.println(Class.forName("java.lang.Object").getClassLoader());

Output:
Here Insert Picture Description
nullstill because the bootstrap class loader can not be accessed directly.

reflection

Class program can analyze the ability (e.g., Method and Method Field methods), it is called 反射.

Java is a critical reflection is considered dynamic language, allowing the program during the execution by means of Reflection API acquired internal information of any type, and internal properties and methods of operation directly. When the aid of reflection, to add a new class in the design or operation, rapid application development tool to dynamically query capabilities of the newly added category

If Class is a description of a class, then we can use REFLECTION Field, Method and Constructor specifically described like this class, to give specific properties, methods, or constructors.

Method

Method The method is used to describe a class of

Get Class category corresponding to "method has"

1. The use of getMethods()the method, although they can not getprivate method, But canInherited methodsAll to get:

		//clazz1还是上文中的Person类对应的Class实例
		Method[] methods1 = clazz1.getMethods();
		for(Method method:methods1)
		{
			System.out.println("All:"+method);
		}

Output: useless Person that is set in a private secretMethod(), but have inherited the Object class toString(), equals()method and so on.
Here Insert Picture Description

2. Through the getDeclaredMethods()acquisition, you can get private methods, but can not get inherited methods.

	Method[] methods2 = clazz1.getDeclaredMethods();
	for(Method method:methods2)
	{
		System.out.println("Declared:"+method);
	}		

Output:
Here Insert Picture Description

Gets the method and the execution method

Gets the methods getDeclaredMethod: by name and parameter list uniquely determined (note that the end of the methods described herein useless s)

		Method method3 = clazz1.getDeclaredMethod("setAge", int.class);
		//int不是类,但是int.class就是个Class类型的对象
		//这里注意int和Integer自己斟酌怎么选用
		System.out.println("Now I get :"+method3);

Output:
Here Insert Picture Description

// execution method invoke: target instance and need to pass parameters.

	Person object = (Person) clazz1.newInstance();
	//给object对象使用method3(setAge)方法,将age设置为10
	method3.invoke(object, 10);
	System.out.println(object.getAge());

Output:
Here Insert Picture Description
successfully modified.

Field

Field encapsulates the class attributes.

Get Class category corresponding to "has an attribute"

1. getFields()The method of obtaining the attribute accessible.

	Field[] field1 = clazz1.getFields();
	for(Field field:field1)
	{
		System.out.println("All:"+field);
	}

As the Person of the two attributes are private, so nothing is output as Field [] it was empty.

2. Use getDeclaredFields()access specific properties, you can access to private property.

		Field[] field2 = clazz1.getDeclaredFields();
		for(Field field:field2)
		{
			System.out.println("Declared:"+field);
		}

Output:
Here Insert Picture Description
successfully get to the age and name attributes.

Access and modify the specified property

By getDeclaredField("属性名")obtaining a property:

		Field field3 = clazz1.getDeclaredField("name");
		System.out.println(field3);

Output:
Here Insert Picture Description

By get(目标对象)the value of a property of the specified object acquired:

		//先创建一个对象
		Person tommy = new Person("Tommy",18);
		//私有变量先设置成可以访问的
		field3.setAccessible(true);
		System.out.println(field3.get(tommy));

Output:
Here Insert Picture Description

By set(目标对象,新设置的属性的值)modifying the value of the property:

	field3.set(tommy, "Jack");
	System.out.println(tommy.getName());

Output Results:
Here Insert Picture Description
Note that modify the properties of reflection in this manner is not calling the appropriate set method.

Get the parent class information using Reflected

For a class object, you may be utilized getSuperclass()to obtain Class instance of the parent class object.
We look at an example:

There are three categories: Grandpa, Father, Son. In which the Son inherit Father, Father inherited Grandpa.
There is a private property in Grandpa class private int grandpaMoney = 1000. We currently use reflection to get the Class instance of the class Son, but now hopes to instantiate a class Grandpa, and modify grandpaMoneyas 2000.

Code ideas are as follows:

		//初始条件
		Son son = new Son();
		Class sonClass = Son.class;
		//开始利用反射
		Class clazz = sonClass
		//如果在当前类找不到这个属性,就一直向上知道Object类
		for(;clazz!=Object.class; clazz=clazz.getSuperclass())
		{
			//获取全部属性
			Field[] myField = clazz.getDeclaredFields();
			//遍历该类中的属性
			for(Field f:myField)
			{
				//如果名字是那个,就开始修改
				if(f.getName().equals("grandpaMoney"))
				{
					//由于是私有的,设置为可修改
					f.setAccessible(true);
					//利用反射实例化一个对象
					Object obj = clazz5.newInstance();
					//修改
					f.set(obj, 2000);
					/任务完成!
				}
			}
		}
Published 33 original articles · won praise 26 · views 2612

Guess you like

Origin blog.csdn.net/qq_43948583/article/details/90951847