Java reflection mechanism

1.1 role of reflection mechanism

         Bytecode files can be manipulated through the emission mechanism in the java language.

         Code snippets can be manipulated through reflection mechanisms. (. class file).

1.2 principle of reflection mechanism:

         1. First, a clear concept: everything is an object - classes are also objects

         2. Then know the contents of the class: modifier constructor field method

         3. Secondly, understand loading: when Animal.class is in the hard disk, it is a file. When it is loaded into memory, it can be regarded as an object, an object of java.lang.class

1.3 package of reflection mechanism related classes

java.lang.reflect.*;

1.4 important categories related to reflection mechanism

         java.lang.Class represents the entire bytecode and represents a type (the entire class)

         java.lang.reflect.Method represents method bytecode in bytecode (method in class)

         java.lang.reflect.Constructor represents the construction method in bytecode (the construction method in class)

         java.lang.reflect.Field represents the attribute bytecode in bytecode (member variable in class: static variable + instance variable)

1.5 there are three ways to obtain the bytecode of the whole class:

         The first: Class c = Class.forName("full package name + class name");

         The second type: Class c = object. getClass();

         Third: Class c = any type. class;

public static void main(String[] args) {
		Class c1=null;
		Class c2=null;
		
		try {
			/*
			 Method 1: class. forName(): the forName() method under class
			  	1.Static method
			  	2.The parameter of the method is a string, which needs to be a complete class name
			  	3.The full class name must have a package name. The java.lang package cannot be omitted
			  	4.Return Class object
			 */
			//Gets the bytecode file for the entire class
			c1=Class.forName("java.lang.String");//c1 represents String.class, or c1 represents String type
			c2=Class.forName("java.util.Date");//c2 stands for Date type
			Class c3=Class.forName("java.lang.Integer");//c3 stands for Integer type
			System.out.println(c1);
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		// Method 2: any object in java has a method: getClass()
		String str="www";
		Class x=str.getClass();//x represents the String.class bytecode file, and x represents the String type
		System.out.println(c1==x);//True (determines the memory address of the object)
		
		Date d=new Date();
		Class dCl=d.getClass();
		System.out.println(c2==dCl);//True (the memory addresses stored in C2 and dCl variables are the same, and both point to the bytecode file in the method area)
		
		// Method 3: any type in java language, including basic data type, has. class attribute
		Class a = String.class;//a stands for String type
		Class b = int.class;//b stands for int type
		Class c = double.class;//c stands for double type
		Class f = Date.class;//f stands for Date type
		System.out.println(x==a);//true
		
	}

Note: when the bytecode file is loaded into the JVM, only one copy is loaded.

one point six   Application of reflection mechanism

         1. The Class obtained through the reflection mechanism can call the parameterless construction method to instantiate the object

         Instantiate the object through the newInstance() method of Class.

// c represents Date type
Class c = Class.forName("java.util.Date");
// Instantiate an object of Date type
Object obj = c.newInstance();

  Note: the parameterless construct is actually called inside the newInstance() method. You must ensure that the parameterless construct exists, otherwise an "instantiation" exception will appear.

public class ReflectTest02 {
	public static void main(String[] args) {
		// Creating objects using construction methods
		User user=new User();
		System.out.println(user);
		// Create objects using the reflection mechanism
		try {
			// The Class is obtained through the reflection mechanism, and the object is instantiated through the Class
			Class c = Class.forName("com.wanho.po.User");//c stands for User type
			// The newInstance() method calls the parameterless construction of the User class to complete the creation of the object.
			// Note: the newInstance() method calls a parameterless construct. Ensure that the parameterless construct exists.
			Object obj = c.newInstance();
			System.out.println(obj);//com.wanho.po.User@6d06d69c
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

         2. Verify the flexibility of reflection mechanism

         Write the java code again, and you can instantiate different objects without changing the java source code. Comply with OCP opening and closing principle: open to extension and close to modification.

public class ReflectTest03 {
	public static void main(String[] args) throws Exception {
// Only one User class object can be created
		//User user = new User();
// Create different instantiated objects by modifying the configuration file		
		// Read the classinfo.properties configuration file through the IO stream
		// Relative path under project / review/classinfo.properties
		FileReader reader = new FileReader("classinfo.properties");
		// Create attribute class object Map
		Properties pro = new Properties();//Key and value are all String types
		// Load profile
		pro.load(reader); 
		// Close flow
		reader.close();
		
		// Get value through key
		String className = pro.getProperty("className");
		System.out.println("Full package name+Class name:"+className);
		//Instantiate objects through reflection mechanism
		Class c = Class.forName(className);
		Object obj = c.newInstance();
		System.out.println("Objects instantiated by reflection:"+obj);
	}
}

         3. If you only want the "static code block" of a class to execute, you can use Class.forName("full class name of the class")

         Important: if you only want the static code block of a class to be executed, and no other code will be executed, you can use: Class.forName("full class name"); The execution of this method will lead to class loading. When the class is loaded, the static code block is executed.

public class ReflectTest04 {
	public static void main(String[] args) {
		try {
			//Class.forName() the execution of this method will cause: class loading
			Class.forName("com.wanho.reflect.MyClass");
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
public class MyClass {
	//Static code blocks are executed when the class is loaded and only once
		static {
			System.out.println("MyClass Class static code block executed!!!!");
		}
}

         4. Research on file path problem

         The following is a general way to get the absolute path of a file. The premise is that the file needs to be in the classpath (src) before it can be used.

public class AboutPath {
	public static void main(String[] args) throws Exception{
		//The disadvantages of this method are: poor portability. The default current path is the root of the project
		//When the code leaves eclipse and goes to another location, the path is not the root of the project, and this path is invalid
		//FileReader reader = new FileReader("classinfo.properties");
		
		//The following is a common path. Even if the code changes location, such writing is still common
		//Note: the premise of using the following general method is that this file must be in the classpath.
		//Under classpath: everything under src is under classpath.
		//src is the root path of the class
		/*
		  	Types of class loader: startup class loader, application class loader and extension class loader
		  	Thread.currentThread() Current thread object
		  	getContextClassLoader() Is the method of the thread object, which can get the classloader object of the current thread
		  	getResource() [Get resources] this is the method of the classloader object. The classloader of the current thread loads resources from the root path of the class by default
		 */
		//The following absolute paths to get files are common
		String path = Thread.currentThread().getContextClassLoader().getResource("classinfo2.properties").getPath();
		//Using the above code, you can obtain the absolute path of a file.
		// /D:/software/eclipse-workspace/review/bin/classinfo2.properties
		System.out.println(path);
		
		// To get the path of db.properties file, you need to start from the root path of the class
		String path2 = Thread.currentThread().getContextClassLoader().getResource("com/wanho/po/db.properties").getPath();
		System.out.println(path2);
	}
}

        5.IoProperties.java

         Note: the classinfo2.properties configuration file is under the classpath (src)

public class IoPropertiesTest {
	public static void main(String[] args) throws Exception{
		//Get the absolute path of a file ---- get the absolute path according to the relative path
//		String path = Thread.currentThread().getContextClassLoader().getResource("classinfo2.properties").getPath();
		//System.out.println(path);
		// Read configuration file
//		FileReader reader = new FileReader(path);
		InputStream reader = Thread.currentThread().getContextClassLoader().getResourceAsStream("classinfo2.properties");
		Properties pro = new Properties();
		// Load profile
		pro.load(reader);
		reader.close();
		// Get value according to key
		String className = pro.getProperty("className");
		System.out.println(className);
	}
}

         6. Resource binder

         A resource binder is provided under the java.util package to obtain the content in the property configuration file.

Note: when using this method, the property configuration file xxx.properties must be placed under the class path.

public class ResourceBundleTest {
	public static void main(String[] args) {
		// Resource binders can only bind xxx.properties files. And this file must be in the classpath. The file extension must also be properties
		// Note: when writing a path, the extension behind the path cannot be written.
//		ResourceBundle bundle = ResourceBundle.getBundle("classinfo2");
		ResourceBundle bundle = ResourceBundle.getBundle("com/wanho/po/db");
		// Get value according to key
		String className = bundle.getString("className");
		System.out.println(className);
		
	}
}

one point seven   Reflection property Field(Field class)

1.7.1 get Field object

methodmeaning
getField(String name)Gets the property object of the specified public modifier
getFields()Get all property objects decorated with public in the class and return the property array Field []
getDeclaredField(String name)Gets the specified property object
getDeclaredFields()Get all property objects and return the property array Field []
getModifiers()Gets the modifier list of the attribute. The returned modifier is an int number, and each number is the modifier code
Modifier.toString(int i)Converts the modifier code to a String and returns the String type
getType()Gets the type of the attribute and returns the Class object
public class ReflectTest05 {
	public static void main(String[] args) throws Exception{
		// Get the entire class
		Class studentClass = Class.forName("com.wanho.po.Student");
		System.out.println("studentClass:"+studentClass);
		// Get class name
		String className = studentClass.getName();
		System.out.println("Full class name:"+className);
		
		String simpleName  = studentClass.getSimpleName();
		System.out.println("Simple class name:"+simpleName);
		
		System.out.println("================");
		// Get all the public decorated properties in the class
		Field[] fields = studentClass.getFields();
		System.out.println(fields.length);
		// Fetch attribute
		Field f = fields[0];
		// Gets the name of the property
		String fieldName = f.getName();
		System.out.println(fieldName);
		
		
		// Get all properties
		Field[] fields2 = studentClass.getDeclaredFields();
		System.out.println(fields2.length);
		System.out.println("================");
		// ergodic
		for(Field field:fields2) {
			// private java.lang.String com.wanho.po.Student.name
			System.out.println(field);
			// Gets the list of modifiers for the property
			int i = field.getModifiers(); //The returned modifier is a number, and each number is the code of the modifier!
			System.out.println(i);
			// Converts the modifier code to a string
			String modifierString = Modifier.toString(i);
			System.out.println("Property modifier:"+modifierString);
			// Gets the type of the property
			Class fieldType = field.getType();
			//String fName = fieldType.getName(); //java.lang.String
			String fName = fieldType.getSimpleName(); //String
			System.out.println("Type of property:"+fName);
			// Gets the name of the property
			System.out.println("The name of the property:"+field.getName());
		}
	}
}

1.7.2 decompile Field

public class ReflectTest06 {
	public static void main(String[] args) throws Exception{
		// Create this string to splice
		StringBuilder sBuilder = new StringBuilder();
		// Get the entire class
		Class studentClass = Class.forName("com.wanho.po.Student");
		sBuilder.append(Modifier.toString(studentClass.getModifiers())+" class "+studentClass.getSimpleName()+"{\n");
		// Get all properties
		Field[] fields = studentClass.getDeclaredFields();
		for(Field field:fields) {
			sBuilder.append("\t");
			sBuilder.append(Modifier.toString(field.getModifiers()));
			sBuilder.append(" ");
			sBuilder.append(field.getType().getSimpleName());
			sBuilder.append(" ");
			sBuilder.append(field.getName());
			sBuilder.append(";\n");
		}
		sBuilder.append("}");
		System.out.println(sBuilder);
	}
}

1.7.3 accessing object properties through reflection mechanism (key)

/**
 * (Master): access object properties through reflection mechanism
 * How to access the properties of a java object through reflection mechanism?
 * 		Assign a set to the property
 * 		get value of property
 */
public class ReflectTest07 {
	public static void main(String[] args) throws Exception{
		//Access the properties of an object without using the reflection mechanism
		Student student = new Student();
		student.no=1001;//Assign 1001 to the no attribute of the student object
						//Element 1: Student object; Element 2: no attribute; Element 3: attribute value 1001
		// Read attribute value
		System.out.println(student.no);
		
		//Using reflection mechanism, how to access the properties of an object. (set  get)
		// Get the entire class
		Class studentClass = Class.forName("com.wanho.po.Student");
		Object obj = studentClass.newInstance();// Student object. (the bottom layer calls the parameterless construction method)
		// Get no attribute (get attribute according to attribute name)
		Field noField=studentClass.getDeclaredField("no");
		// Assign values to attributes
		/*
			Although the reflection mechanism is used, three elements are indispensable:
				Element 1: obj object
				Element 2: no attribute
				Element 3: no attribute value 1002
		 */
		noField.set(obj, 1002);//Assign 1002 to the no attribute of obj object (Student object)
		// Read the value of the property
		// Two elements: get the value of no attribute of obj object.
		System.out.println(noField.get(obj));
		
		// Can I access private properties---- may not
		Field nameField=studentClass.getDeclaredField("name");
		//System.out.println(nameField);
		// Breaking encapsulation (disadvantage of reflection mechanism: breaking encapsulation may leave opportunities for criminals!!!)
		// After this setting, private can also be accessed externally.
		nameField.setAccessible(true);
		
		// Assign a value to the name attribute
		nameField.set(obj, "marry");
		// Gets the value of the name property
		System.out.println(nameField.get(obj));
	}
}

one point eight   Reflection Method class (emphasis)

1.8.1 reflection Method

methodmeaning
getMethods()Get all public method objects
getMethod(String name, Class... parameterTypes)Gets the method object of the specified public
getDeclaredMethods()Get all Method objects and return Method []
getDeclaredMethod(String name, Class... parameterTypes)Gets the specified method object
getParameterTypes()Get the parameter list and return Class []
public class ReflectTest08 {
	public static void main(String[] args) throws Exception{
		// Get class
		Class uSClass = Class.forName("com.wanho.service.UserService");
		// Get all methods
		Method[] methods = uSClass.getDeclaredMethods();
		// ergodic
		for(Method method:methods) {
			// Get modifier list
			System.out.println(Modifier.toString(method.getModifiers()));
			// Gets the return value type of the method
			System.out.println(method.getReturnType().getSimpleName());
			// Get method name
			System.out.println(method.getName());
			// Get parameter list
			Class[] parameterTypes = method.getParameterTypes();
			// ergodic
			for(Class parameterType:parameterTypes) {
				System.out.println(parameterType.getSimpleName());
			}
		}
	}
}

1.8.2 decompile Method

public class ReflectTest09 {
	public static void main(String[] args) throws Exception{
		StringBuilder s = new StringBuilder();
		// Get class
		Class uSClass = Class.forName("java.lang.String");
		s.append(Modifier.toString(uSClass.getModifiers())+" class "+uSClass.getSimpleName()+"{\n");
		Method[] methods = uSClass.getDeclaredMethods();
		for(Method method:methods) {
			s.append("\t");
			s.append(Modifier.toString(method.getModifiers()));
			s.append(" ");
			s.append(method.getReturnType().getSimpleName());
			s.append(" ");
			s.append(method.getName());
			s.append("(");
			Class[] parameterTypes = method.getParameterTypes();
			// ergodic
			for(Class parameterType:parameterTypes) {
				s.append(parameterType.getSimpleName());
				s.append(",");
			}
			s.deleteCharAt(s.length()-1);
			
			s.append(")");
			
			s.append("{}\n");
		}
		s.append("}");
		System.out.println(s);
	}
}

1.8.3 calling methods through reflection mechanism (key points)

invoke() Method in Method class

methodmeaning
invoke(Object obj, Object ...value)Call this method
/**
 * 	((emphasis) how to call an object's method through reflection mechanism
 * 	Five stars ※※※※※
 * 
 * 	The reflection mechanism makes the code universal, and the changeable contents are written to the configuration file,
 * 	By modifying the configuration file, you can create different objects and call different methods,
 * 	But the java code doesn't need to be changed. This is the charm of reflection mechanism.
 * @author Lucky
 *
 */
public class ReflectTest10 {
	public static void main(String[] args) throws Exception{
		// How to call a method without using reflection mechanism
		//create object
		UserService userService = new UserService();
		// Call method
		/*
		 	Element analysis:
		 		Element 1: userService object
		 		Element 2: login method name
		 		Element 3: argument list
		 		Element 4: return value
		 */
		boolean f= userService.login("admin", "123");
		System.out.println(f);
		//userService.logout();
		
		// Use reflection mechanism
		Class c = Class.forName("com.wanho.service.UserService");
		// create object
		Object obj = c.newInstance();
		// Get method object
		Method loginMethod = c.getDeclaredMethod("login", String.class,String.class);
		// Call method
		// Calling a method requires four elements.
		// One of the most important methods of reflection mechanism must be remembered.
		// Four elements
		/*
		  loginMethod method
		  obj object
		  "admin","123"Actual parameters
		  retValue Return value
		 */
		Object retValue = loginMethod.invoke(obj, "admin", "123");//Calling methods with invoke
		System.out.println(retValue);
	}
}

one point nine   Reflection Constructor

1.9.1 decompile Constructor

public class ReflectTest11 {
	public static void main(String[] args) throws Exception{
		StringBuilder s = new StringBuilder();
		Class vipClass = Class.forName("com.wanho.po.Vip");
		// Gets the modifier of the class
		s.append(Modifier.toString(vipClass.getModifiers()));
		s.append(" class ");
		// Get class name
		s.append(vipClass.getSimpleName());
		s.append("{\n");
		// Splicing construction method
		Constructor[] constructors = vipClass.getDeclaredConstructors();
		for(Constructor constructor : constructors) {
			s.append("\t");
			// Gets the modifier of the constructor
			s.append(Modifier.toString(constructor.getModifiers()));
			s.append(" ");
			s.append(vipClass.getSimpleName());
			s.append("(");
			// Splicing parameters
			Class[] parameterTypes = constructor.getParameterTypes();
			for(Class parameterType : parameterTypes) {
				s.append(parameterType.getSimpleName());
				s.append(",");
			}
			if(parameterTypes.length > 0) {
				// Deletes the string at the last subscript position
				s.deleteCharAt(s.length() - 1);
			}
			s.append("){}\n");
		}
		s.append("}");
		System.out.println(s);
	}
}

1.9.2 calling construction method through reflection mechanism

public class ReflectTest12 {
	public static void main(String[] args) throws Exception{
		// Create objects without reflection
		Vip vip = new Vip();
		Vip vip2 = new Vip(1001, "marry", "1999", true);
		
		// Create objects using the reflection mechanism
		Class vipClass = Class.forName("com.wanho.po.Vip");
		// Call parameterless construction
		Object obj = vipClass.newInstance();
		System.out.println(obj);
		// Call parameterized constructor
		// 1. Get construction method
		Constructor con = vipClass.getDeclaredConstructor(int.class);
		// 2. Call the new object of the constructor
		Object obj2 = con.newInstance(1002);
		System.out.println(obj2);
		
		// Method for obtaining parameterless construction
		Constructor con2 = vipClass.getDeclaredConstructor();
		Object obj3 = con2.newInstance();
		System.out.println(obj3);
		
	}
}

one point one zero   Get parent class and parent interface through reflection

public class ReflectTest13 {
	public static void main(String[] args) throws Exception{
		// Get String class
		Class stringClass = Class.forName("java.lang.String");
		
		// Gets the parent class of the String class
		Class superClass = stringClass.getSuperclass();
		System.out.println("String Parent class of:"+superClass.getName());
		
		// Get all interfaces implemented by the String class (a class can implement multiple interfaces)
		Class[] interfaces = stringClass.getInterfaces();
		for(Class inter : interfaces) {
			System.out.println("String Interface implemented by class:"+inter.getName());
		}
	}
}

Tags: Java

Posted on Sat, 23 Oct 2021 00:45:25 -0400 by SOL-ion