1, The concept of reflection
1. What is reflection? Why use reflection?
When we write code before, we first write classes, then create objects with classes, and call members such as methods through class names or object names.
==> The name and members of this class should be determined during compilation.
For example:
public class Student{ private int id; private String name; public Student(){ } public Student(int id, String name){ this.id = id; this.name = name; } public void setId(int id){ this.id = id; } public int getId(){ return id; } //... } public class TestStudent{ public static void main(String[] args){ Student stu1 = new Student(); Student stu2 = new Student(1,"Zhang San"); System.out.println(stu1.getId()); } }
Now, in the development process, we will encounter such situations: during compilation, the type is unknown or does not exist during compilation,
However, we need to complete the new object, calling method and other codes first. The type, etc. can only be determined at runtime.
Class -- > class information
Class object -- > class information
The Class object of the Class is the mirror image of the Class. This process is compared to reflection.
2. Source of reflection: object of Class type
public class TestReflect { public static void main(String[] args) { //Write the code to create the object first Properties pro = new Properties();//Map series, with key,value, key and value of String type try { pro.load(TestReflect.class.getClassLoader().getResourceAsStream("info.properties")); } catch (IOException e) { e.printStackTrace(); } try { Class<?> clazz = Class.forName(pro.getProperty("className"));//"className" is a key in the info.properties file //pro.getProperty("className") is obtained, but the key in the info.properties file is the value value of className, that is, the value on the right of className = //new object Object obj = clazz.newInstance(); System.out.println(obj); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } } }
3. Where are the properties files?
(1) Put it in the root directory of src
(2) Put it in a bag
(3) Outside src, under the root directory of the module
public class TestLoaderProperties { public static void main(String[] args)throws Exception { Properties pro = new Properties(); ClassLoader classLoader = TestLoaderProperties.class.getClassLoader(); pro.load(classLoader.getResourceAsStream("info.properties"));//src root directory System.out.println(pro); System.out.println("---------------------------"); Properties pro2 = new Properties(); ClassLoader classLoader2 = TestLoaderProperties.class.getClassLoader(); pro2.load(classLoader2.getResourceAsStream("com/atguigu/reflect/pkg.properties"));//com.atguigu.reflect package System.out.println(pro2); System.out.println("----------------------"); Properties pro3 = new Properties(); //If it is run in the main method, the module name must be added. The relative path of main is relative to project pro3.load(new FileInputStream("day0831_teacher_code/out.properties"));//src, under the module root directory System.out.println(pro3); } @Test public void test() throws Exception { //The relative path of JUnit is relative to the module Properties pro3 = new Properties(); pro3.load(new FileInputStream("out.properties"));//src, under the module root directory System.out.println(pro3); } }
2, Class loading process
3. How did the Class object come from?
When a Java program runs, it will first "load" the class information such as the. Class file of the required class into memory,
After each Java type is "loaded", it will be stored and represented by a Class object.
4. Class loading is divided into three stages: (understand)
(1) load: first read the data of the. class file into memory
(2) Connect (link)
A: Test legitimacy
For example, check the format of bytecode file, including version, etc
The of bytecode file must be in cafebabe
B: Prepare the corresponding memory
Prepare the new Class object,
Class's static variable data storage memory (method area) This is the default value and has not been initialized
Class, which will be initialized directly at this time. public static final int MAX_VALUE = 100;
C: Analysis
Replace the symbol reference in bytecode file with address reference
For example: Student class
public class Student {
private int id;
private String name;
. . . .
}
For example, string and int are symbolic references,
String and int are also Java data types and have their Class objects in memory. At this time, replace string and int with the first addresses of the Class objects of these two types in memory.
Why replace it with an address reference?
In this way, when running, you don't need to find it now, and you can get the corresponding information directly according to the address.
After the first two steps, the Class object is, but the static variable of this Class has not been initialized.
(3) Initialization
Run the < clinit > method of this class
After the first three steps, the Class object is and the static variable is initialized.
5. Who completes the loading of classes?
Class loading is done by the class loader ClassLoader. The bottom layer has a special thread to load the class.
Class loaders are divided into four types:
(1) Boot class loader: responsible for the classes in the core class library and the classes under rt.jar
Note: the boot class loader is written in C language, so its object cannot be obtained at the Java level
(2) Extclassloader: it is responsible for jar in ext extension directory under lib directory under JRE
(3) Application class loader: responsible for the classes written by programmers themselves
(4) Custom class loader: it is also used to load classes written by programmers, and load some special classes and special directories
For example, if the bytecode needs to be encrypted, it must be decrypted with the corresponding class loader before it can be loaded normally.
For example, bytecode files are not placed under the normal classpath. For example, the classpath of IDEA is out.
The classpath of tomcat server is special, so it can't be loaded with ordinary classloader, so it needs to be loaded with custom classloader. tomcat writes custom classloader.
6. How do I get the class loader?
The Class object of the Class can call the getClassLoader() method to get the Class loader object.
7. Class loaded collaboration mode: parent delegation mode, which is designed for security.
Parents: parents
Parents:
The application class loader treats the extension class loader as a parent, but not an inheritance. There is a parent member variable in the application class loader to record the extension class loader.
The extension class loader treats the boot class loader as a parent, but not an inheritance. There is a parent member variable in the extension class loader to record the boot class loader.
Process Description:
(1) When our application Class loader receives the loading task, first check whether this Class has been loaded in memory. If it has been loaded, it will not be loaded again, and the Class object will be returned directly.
If it has not been loaded, first hand over the task to the "parents", that is, the extension class loader.
For example, the application class loader receives the task of loading "java.lang.String". If the class has not been loaded, the task is sent to the extension class loader
For example, the application class loader receives the task of loading "java.lang.Atguigu". If the class has not been loaded, the task is sent to the extension class loader
(2) After receiving the loading task, the extension Class loader also checks whether this Class has been loaded in memory. If it has been loaded, it will not be loaded again and will directly return the Class object.
If it has not been loaded, the task is handed over to the "parents", that is, the boot class loader.
For example, the extension class loader receives the task of loading "java.lang.String". If this class has not been loaded, the task is sent to the boot class loader
For example, the extension class loader receives the task of loading "java.lang.Atguigu". If this class has not been loaded, give the task to the boot class loader
(3) After receiving the loading task, the boot Class loader also checks whether this Class has been loaded in memory. If it has been loaded, it will not be loaded again and will directly return the Class object.
If it has not been loaded, try to search this class in the directory it is responsible for,
For example, the boot Class loader receives the task of loading "java.lang.String", loads it in the directory it is responsible for, finds it in rt.jar, and returns the Class object if it is found.
For example, the boot Class loader receives the task of loading "java.lang.Atguigu", loads it in the directory it is responsible for, finds it in rt.jar, and returns the Class object if it is found.
If not, pass the task back to the extension class loader
(4) When the extension Class loader receives the task of guiding the Class to return again, it will search the Class in the directory it is responsible for. If it finds it, it will return the Class object.
If not, send the task back to the application class loader
(5) The application Class loader is connected to the extension Class loader again For the returned task, it will search for this Class in the directory it is responsible for. If it is found, it will return the Class object.
If it is not found, an error ClassNotFoundException is reported
Summary:
The class loading process is completed by the class loader. There are four (usually three) working modes. The working mode is the two parent delegation mode for security.
The result of Class loading is to get the Class object of a Class.
public class TestClassLoad { public static void main(String[] args) { System.out.println(MyClass.MAX_VALUE); System.out.println(MyClass.a); System.out.println("-------------------------------"); //String.class gets the class object of string class ClassLoader classLoader = String.class.getClassLoader(); System.out.println("load String Class loader:" + classLoader);//null //TestClassLoad.class gets the Class object of TestClassLoad Class ClassLoader loader = TestClassLoad.class.getClassLoader(); System.out.println("Programmer custom class TestClassLoad Class loader object for class:" + loader);//sun.misc.Launcher$AppClassLoader@18b4aac2 ClassLoader parent = loader.getParent(); System.out.println("app Class loader parent: " + parent); System.out.println("-------------------------------"); try { //Class.forName("com.atguigu.loader.TestLoader") gets the class object of TestLoader Class clazz = Class.forName("com.atguigu.loader.TestLoader"); System.out.println("stay JRE/lib/ext Under directory TestLoader Class loader for class:" + clazz.getClassLoader()); //sun.misc.Launcher$ExtClassLoader@45ee12a7 ClassLoader ext = clazz.getClassLoader(); System.out.println("ext Extension class loader parent: "+ ext.getParent()); } catch (ClassNotFoundException e) { e.printStackTrace(); } try { //Class.forName("java.lang.Atguigu") gets the class object of Atguigu Class clazz = Class.forName("java.lang.Atguigu");//ClassNotFoundException: System.out.println("Atguigu Class Class Object:" + clazz); } catch (ClassNotFoundException e) { e.printStackTrace(); } } } class MyClass{ public static final int MAX_VALUE = 100; //Direct assignment in the preparation stage of class loading public static int a = 100;//The initialization phase of class loading completes the assignment static{ System.out.println("Static code block");//Class initialization execution } }
3, Reflection source Class
1. Why is there a Class type?
Java data types, especially reference data types, such as classes,
They have many common features:
Take class as an example
There are class names, modifiers, parent classes, parent interfaces, member variables, member methods, constructors
You can create objects, call methods and other operations
Java class is an abstract description of a class of things with the same characteristics.
Class is an abstract description of Java data types.
Class is an object that represents a specific Java data type.
java.lang.String type. There is a Class object in JAVA memory to represent it, and this object is unique.
java.lang.Integer type. There is also a Class object in JAVA memory to represent it, and this object is also unique.
If two variables are of the same type, they use the same Class object.
2. Which Java types have Class objects?
An instance of the Class represents classes and interfaces in a running Java application.
Enumeration is a kind and annotation is an interface.
Each array belongs to a Class mapped as a Class object, which is shared by all arrays with the same element type and dimension.
The basic Java types (boolean, byte, char, short, int, long, float, and double) and the keyword void are also represented as Class objects.
Conclusion: all Java data types have Class objects.
3. How to get a Class object?
Class has no public constructor. Class objects are automatically constructed by the Java virtual machine when loading classes and by calling the defineClass method in the class loader.
There are four ways to obtain: (must master)
(1) Type name.class
Applies to types known and existing by the compiler
(2) Object. getClass()
This method is used in the Object class to get the runtime type of the Object
Get the runtime type of the object when applicable to polymorphic references
(3) Class.forName("full name of type")
Applies to types that are unknown or do not exist during compilation
(4) Class loader object. loadClass("full name of type")
public class TestClass { @Test public void test06(){ //TestClass.class get the Class object of TestClass //TestClass.class.getClassLoader() gets the classloader object that loads TestClass ClassLoader classLoader = TestClass.class.getClassLoader(); try { //Use this classloader object to load other classes Class<?> c1 = classLoader.loadClass("com.atguigu.bean.Teacher"); Class c2 = Teacher.class; System.out.println(c1 == c2); } catch (ClassNotFoundException e) { e.printStackTrace(); } } @Test public void test05(){ try { Class<?> c1 = Class.forName("java.lang.String"); Object obj = "hello";//Polymorphic reference Class<?> c2 = obj.getClass(); Class<?> c3 = String.class; System.out.println(c1 == c2); System.out.println(c1 == c3); } catch (ClassNotFoundException e) { e.printStackTrace(); } } @Test public void test04(){ int[] arr1 = {1,2,3,4,5}; int[] arr2 = new int[10]; Class c1 = arr1.getClass(); Class c2 = arr2.getClass(); System.out.println(c1 == c2);//true only looks at the type and dimension of the element, not the value of the element and the length of the array } @Test public void test03(){ Object obj = "hello";//Polymorphic reference Class<?> c1 = obj.getClass(); //Get the runtime type of obj, which is a Class object of String type Class stringClass = String.class; System.out.println(c1 == stringClass);//true } @Test public void test02(){ Class c1 = "hello".getClass();//Class object representing the runtime type String of the object "hello" Class stringClass = String.class; //The result is a Class object representing a String type //If the address of the comparison object is the same object, true will be returned System.out.println(c1 == stringClass);//true. Both of them are java.lang.String. In memory, there is only one Class object to represent the String type } //Demonstrate that all Java data types need their own Class objects @Test public void test01(){ //class Class stringClass = String.class; Class integerClass = Integer.class; //Basic data type and void Class intClass = int.class; Class voidClass = void.class; System.out.println(stringClass == integerClass) ;//false System.out.println(intClass == integerClass) ;//false Class intArrayClass = int[].class; Class intArray2Class = int[][].class; System.out.println(intArrayClass == intArray2Class);//false Class stringArrayClass = String[].class; System.out.println(intArrayClass == stringArrayClass);//false System.out.println(stringClass == stringArrayClass);//false //Interface Class s1 = Serializable.class; //annotation Class o1 = Override.class; //enumeration Class m1 = Month.class; } }
4, Application of reflection
1. Get class information
When you get the Class object of a Class, you can see through the Class.
public class TestClassInfo { public static void main(String[] args)throws Exception { Class<?> clazz = Class.forName("java.lang.String");//Here, take String as an example. It can be any other type //Get Class information through Class object //(1) Get package Package pkg = clazz.getPackage(); System.out.println("pkg = " + pkg); //(2) Get type name String name = clazz.getName(); System.out.println("name = " + name); //Full name = package + class name //(3) Modifier int modifiers = clazz.getModifiers(); System.out.println("modifiers = " + modifiers);//17 /* java.lang.reflect The Modifier under the package describes all JAVA modifiers Hexadecimal decimal binary public static final int PUBLIC = 0x00000001; 1 1 public static final int PRIVATE = 0x00000002; 2 10 public static final int PROTECTED = 0x00000004; 4 100 public static final int STATIC = 0x00000008; 8 1000 public static final int FINAL = 0x00000010; 16 10000 Each modifier is to the nth power of 2. Their binary characteristic is that one bit is 1 and the others are 0 public: 00000000 00000000 00000000 00000001 final : 00000000 00000000 00000000 00010000 |Bitwise OR: 00000000 00000000 00010001 17 17 Binary of: 00000000 00000000 000100010001 & public: 00000000 00000000 00000000 00000001 00000000 00000000 00000000 00000001 Non 0, indicating public 17 Binary of: 00000000 00000000 000100010001 & private: 00000000 00000000 00000000 00000010 00000000 00000000 00000000 00000000 0,It means there is no private */ System.out.println(Modifier.toString(modifiers));//public final //(4) Parent class Class<?> superclass = clazz.getSuperclass(); System.out.println("Parent class:" + superclass); //(5) Parent interfaces System.out.println("Parent interfaces are:"); Class<?>[] interfaces = clazz.getInterfaces(); for (Class<?> anInterface : interfaces) { System.out.println(anInterface); } //(6) Member variables /* Field getField(String name): Get a public property according to the property name Field getDeclaredField(String name): Gets a declared property based on the property name Field[] getFields() : Get all public properties Field[] getDeclaredFields() : Get all declared properties */ System.out.println("Get all properties:"); Field[] declaredFields = clazz.getDeclaredFields(); for (Field declaredField : declaredFields) { System.out.println(declaredField); } //Get one of the properties Field valueField = clazz.getDeclaredField("value"); int mod = valueField.getModifiers(); System.out.println("mod = " + mod);//18 System.out.println("value Modifier for property:" + Modifier.toString(mod));//private final System.out.println("value Name of:" + valueField.getName()); System.out.println("value Data type:" + valueField.getType());//[C] represents one-dimensional array, and C represents char type //(7) Get all constructors /* Constructor<T> getConstructor(Class<?>... parameterTypes): Get a public constructor Constructor<?>[] getConstructors(): All public constructors Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) : Gets the constructor of a declaration Constructor<?>[] getDeclaredConstructors() : Gets the constructor for all declarations of a */ System.out.println("All constructors:"); Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors(); for (Constructor<?> declaredConstructor : declaredConstructors) { System.out.println(declaredConstructor); } //Get a constructor //Constructor<T> getDeclaredConstructor(Class<?>... Parametertypes): gets the constructor of a declaration //(Class<?>... Parametertypes), because the number of formal parameters of the constructor is 0~n //Constructors can be overloaded and distinguished by the formal parameter list of constructors. Therefore, to obtain a constructor, you need to specify the type of the formal parameter list of the piece constructor //public java.lang.String(byte[]) Constructor c = clazz.getDeclaredConstructor(byte[].class);//Get the constructor of String class whose formal parameter is byte [] type System.out.println("Formal parameter is byte[]Constructor of type:" + c); //(8) All methods /* Method getDeclaredMethod(String name, Class<?>... parameterTypes): Get a declared method, and determine a method by specifying the name of the method and the formal parameter list of the method Method[] getDeclaredMethods(): Gets all declared methods Method getMethod(String name, Class<?>... parameterTypes): Get a public method, and determine a method by specifying the name of the method and the formal parameter list of the method Method[] getMethods(): Get all public methods */ System.out.println("All the ways:"); Method[] declaredMethods = clazz.getDeclaredMethods(); for (Method declaredMethod : declaredMethods) { System.out.println(declaredMethod); } } }
2. Create objects of any type at run time
Any type: excluding basic data type, void, abstract class, interface, etc
Any type: refers to the type of object that can be created.
Briefly describe:
Later, we will write Java EE Projects.
( 1) The server-side code written later runs in the web server (for example, tomcat),
There are many classes on the server side, some of which are created by the web server. For example: servlet class (representing jsp page)
( 2) The later projects will use spring,mybatis and other frameworks, and our classes will also be handed over to the spring framework to help us manage,
Our class objects are created by the spring framework.
The web server, spring,mybatis and other framework codes have been written, and our class was written later.
The new object code is written in advance in the web server, spring,mybatis and other frameworks. We later passed the specific new object class
The xx.xml file tells the server or framework, and then they can read the configuration file to get the "Class name" and the corresponding Class object,
Then the new object.
Method 1: directly use the newInstance() method of Class class to create objects
There is a frequently used method in Class:
T newInstance(): create a new instance of the Class represented by this Class object.
If this Class object represents a String type, newInstance() creates a String object
If this Class object represents the Student type, newInstance() creates the Student object
If this Class object represents the Date type, newInstance() creates the Date object
To create an instance object in this way, this type must have a public parameterless structure, otherwise it will report illegalaccessexception and instantiationexception.
Report IllegalAccessException: there is a problem with the permission modifier of the constructor
InstantiationException: no parameterless construct
Method 2: first obtain the constructor object of this class, and then create the object through the newInstance method of the constructor object
In this way, the constructor can be parameterless, parameterless, or any permission modification.
public class TestNewInstance { @Test public void test3() throws IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { /* Suppose the configuration file of the framework is called info.properties There are various configuration information such as key=value. One key is className, and its value is the type name of the object you want to create For example: className=java.util.Date */ //(1) First, read the configuration file //If the info.properties file is in the root directory of src //src is a source code file. Everything in it will be compiled by the compiler into the class path (out directory), that is, the configuration file under src will be together with the. Class file //The. Class file can be loaded through "application class loader", and the configuration file under src can also be loaded through "application class loader" Properties properties = new Properties(); /* TestNewInstance Class is a class written by the programmer himself, so it is loaded by the "application class loader" TestNewInstance.class Get its Class object TestNewInstance.class.getClassLoader()Get the class loader object, that is, the "application class loader" object */ ClassLoader classLoader = TestNewInstance.class.getClassLoader();//Gets the application class loader object properties.load(classLoader.getResourceAsStream("info.properties")); //After the above code, the data in "info.properties" is stored in the map of properties and stored in the form of (key,value) //(2) Step 2: get the value according to the key to get the name of the class to be loaded String className = properties.getProperty("className"); //(3) Step 3: get its Class object in memory Class clazz = Class.forName(className);//If this class is not in memory, the application class loader will try to load it. If it is not found, it will report ClassNotFoundException //(4) Get a constructor object //For example, I want to get the public Teacher(String name,double salary) constructor Constructor c = clazz.getDeclaredConstructor(String.class,double.class);//String.class represents that the type of formal parameter is string type //(5) Object call through constructor //java.lang.reflect.Constructor class T newInstance(Object... initargs) //The parameters of newInstance(Object... initargs) are finally the arguments passed to the constructor you call //c.newInstance("Zhang San", 15000); "Zhang San" here is equivalent to your new Teacher("Zhang San", 15000) //You can do this if the called constructor cannot create an object because of the visibility of the permission modifier c.setAccessible(true);//Permission modifier check skipped Object obj = c.newInstance("Zhang San",15000); System.out.println(obj); } @Test public void test2() throws IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { /* Suppose the configuration file of the framework is called info.properties There are various configuration information such as key=value. One key is className, and its value is the type name of the object you want to create For example: className=java.util.Date */ //(1) First, read the configuration file //If the info.properties file is in the root directory of src //src is a source code file. Everything in it will be compiled by the compiler into the class path (out directory), that is, the configuration file under src will be together with the. Class file //The. Class file can be loaded through "application class loader", and the configuration file under src can also be loaded through "application class loader" Properties properties = new Properties(); /* TestNewInstance Class is a class written by the programmer himself, so it is loaded by the "application class loader" TestNewInstance.class Get its Class object TestNewInstance.class.getClassLoader()Get the class loader object, that is, the "application class loader" object */ ClassLoader classLoader = TestNewInstance.class.getClassLoader();//Gets the application class loader object properties.load(classLoader.getResourceAsStream("info.properties")); //After the above code, the data in "info.properties" is stored in the map of properties and stored in the form of (key,value) //(2) Step 2: get the value according to the key to get the name of the class to be loaded String className = properties.getProperty("className"); //(3) Step 3: get its Class object in memory Class clazz = Class.forName(className);//If this class is not in memory, the application class loader will try to load it. If it is not found, it will report ClassNotFoundException //(4) Get a constructor object //For example, I want to get the public Teacher(String name) constructor of the Teacher class Constructor c = clazz.getDeclaredConstructor(String.class);//String.class represents that the type of formal parameter is string type //(5) Object call through constructor //java.lang.reflect.Constructor class T newInstance(Object... initargs) //The parameters of newInstance(Object... initargs) are finally the arguments passed to the constructor you call //c.newInstance("Zhang San"); "Zhang San" here is equivalent to your new Teacher("Zhang San") Object obj = c.newInstance("Zhang San"); System.out.println(obj); } @Test public void test() throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException { /* Suppose the configuration file of the framework is called info.properties There are various configuration information such as key=value. One key is className, and its value is the type name of the object you want to create For example: className=java.util.Date */ //(1) First, read the configuration file //If the info.properties file is in the root directory of src //src is a source code file. Everything in it will be compiled by the compiler into the class path (out directory), that is, the configuration file under src will be together with the. Class file //The. Class file can be loaded through "application class loader", and the configuration file under src can also be loaded through "application class loader" Properties properties = new Properties(); /* TestNewInstance Class is a class written by the programmer himself, so it is loaded by the "application class loader" TestNewInstance.class Get its Class object TestNewInstance.class.getClassLoader()Get the class loader object, that is, the "application class loader" object */ ClassLoader classLoader = TestNewInstance.class.getClassLoader();//Gets the application class loader object properties.load(classLoader.getResourceAsStream("info.properties")); //After the above code, the data in "info.properties" is stored in the map of properties and stored in the form of (key,value) //(2) Step 2: get the value according to the key to get the name of the class to be loaded String className = properties.getProperty("className"); //(3) Step 3: get its Class object in memory Class clazz = Class.forName(className);//If this class is not in memory, the application class loader will try to load it. If it is not found, it will report ClassNotFoundException //(4) Step 4: create object // Through the Class object of this Class, call the newInstance() method to create the object Object obj = clazz.newInstance(); System.out.println(obj); } }
3. The properties of any object can be accessed / manipulated at run time
Steps:
(1) Get the Class object first
(2) Get the Field object of the property you want to operate on / access
(3) If you want to access a static variable, you can access the value of the static variable by calling the set/get method of the Field object
If you want to access a non static variable, you also need to create an object of this class, and then the set/get method of the Field object can access the value of the non static variable
public class TestAccessField { @Test public void test03() throws NoSuchFieldException, IllegalAccessException { String str = "hello"; //Modify the string content of str, assuming that e is changed to a Class<? extends String> stringClass = str.getClass();//Get the Class object of String Class Field valueField = stringClass.getDeclaredField("value");//Get the private final char value [] in the String class; //Because the value attribute is private in the String class, you need to skip the permission modifier check valueField.setAccessible(true); Object o = valueField.get(str);//Get the value array of str string char[] arr = (char[]) o;//Cast to char [] type arr[1] = 'a'; System.out.println(str);//hallo } @Test public void test02() throws IOException, ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException { //(1) First, read the configuration file Properties properties = new Properties(); ClassLoader classLoader = TestNewInstance.class.getClassLoader();//Gets the application class loader object properties.load(classLoader.getResourceAsStream("info.properties")); //(2) Step 2: get the value according to the key to get the name of the class to be loaded String className = properties.getProperty("className"); //(3) Step 3: get its Class object in memory Class clazz = Class.forName(className);//If this class is not in memory, the application class loader will try to load it. If it is not found, it will report ClassNotFoundException //(4) Step 4: get the Field object of the attribute to be operated Field companyField = clazz.getDeclaredField("company"); //Because the company attribute is static, there is no need to create a Teacher object //(5) Call the set and get methods of the Field object to operate the company property //If the property is private, you can avoid permission modifier checking through the following operations companyField.setAccessible(true); companyField.set(null,"Shang Silicon Valley"); Object value = companyField.get(null); System.out.println("value = " + value); } @Test public void test01() throws IOException, ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException { //(1) First, read the configuration file Properties properties = new Properties(); ClassLoader classLoader = TestNewInstance.class.getClassLoader();//Gets the application class loader object properties.load(classLoader.getResourceAsStream("info.properties")); //(2) Step 2: get the value according to the key to get the name of the class to be loaded String className = properties.getProperty("className"); //(3) Step 3: get its Class object in memory Class clazz = Class.forName(className);//If this class is not in memory, the application class loader will try to load it. If it is not found, it will report ClassNotFoundException //(4) Step 4: get the Field object of the attribute to be operated Field nameField = clazz.getDeclaredField("name"); //(5) Because the name attribute is non static, you need to create a Teacher object to manipulate it //Here, Teacher has a public parameterless structure, Object teacher = clazz.newInstance(); //(6) Call the set and get methods of the Field object to operate on the name property //If the property is private, you can avoid permission modifier checking through the following operations nameField.setAccessible(true); nameField.set(teacher,"Li Si"); Object value = nameField.get(teacher); System.out.println("value = " + value); System.out.println(teacher); } }
4. Call any method at run time
Demonstrates calling various methods in the com.atguigu.test.Father class through reflection
public class TestInvokeMethod { @Test public void test4() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException { //(1) The first step is to obtain the Class object of the Father Class through one of the four methods we talked about Class clazz = Class.forName("com.atguigu.test.Father"); //(2) Step 2: get the Method object of the Method you want to call // public int sum(int a, int b) is a non static method Method sumMethod = clazz.getDeclaredMethod("sum",int.class,int.class); //(3) Step 3: if it is a non static method, you need to create an object of the Father class first Object obj = clazz.newInstance();//Create an object of the Father class. Because clazz represents the Father class, the Father class is required to have a public parameterless structure Object value = sumMethod.invoke(obj, 1, 5);//Obj here means to call the fun method through the Father object obj, which is equivalent to ((Father)obj).fun(); //If the sum method has a return value, the return value is passed back through the invoke call System.out.println("value = " + value); } @Test public void test3() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException { //(1) The first step is to obtain the Class object of the Father Class through one of the four methods we talked about Class clazz = Class.forName("com.atguigu.test.Father"); //(2) Step 2: get the Method object of the Method you want to call // public void fun() is a non static method Method funMethod = clazz.getDeclaredMethod("fun"); //(3) Step 3: if it is a non static method, you need to create an object of the Father class first Object obj = clazz.newInstance();//Create an object of the Father class. Because clazz represents the Father class, the Father class is required to have a public parameterless structure funMethod.invoke(obj);//Obj here means to call the fun method through the Father object obj, which is equivalent to ((Father)obj).fun(); } @Test public void test2() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { //(1) The first step is to obtain the Class object of the Father Class through one of the four methods we talked about Class clazz = Class.forName("com.atguigu.test.Father"); //(2) Step 2: get the Method object of the Method you want to call // public static void test(int a) is a static method Method testMethod = clazz.getDeclaredMethod("test",int.class); //int.class means to get the test method with a formal parameter of type int //(3) Step 3: if it is a static method, it can be called directly testMethod.invoke(null, 100);//null here means that an object of the Father class is not required //The 100 here is the 100 assigned to the formal parameter of the test method } @Test public void test1() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { //(1) The first step is to obtain the Class object of the Father Class through one of the four methods we talked about Class clazz = Class.forName("com.atguigu.test.Father"); //(2) Step 2: get the Method object of the Method you want to call // public static void test() is a static method Method testMethod = clazz.getDeclaredMethod("test"); //(3) Step 3: if it is a static method, it can be called directly testMethod.invoke(null);//null here means that an object of the Father class is not required } }
5. Gets information about the generic parent class
Demonstrates how to obtain the generic information of the generic parent class Father of the subclass Sub. when the subclass Sub inherits the parent class Father, it specifies the generic information Father < string, integer >
public class TestGenericFather { public static void main(String[] args)throws Exception { //(1) The first step is to obtain the Class object of the Sub Class Class clazz = Class.forName("com.atguigu.reflect.kuo.Sub"); //(2) Step 2: get the Type object of the generic parent class Class superclass = clazz.getSuperclass(); System.out.println(superclass);//Generic information is not available in this way Type genericSuperclass = clazz.getGenericSuperclass(); /* JDK1.5 Generics are introduced. Originally, all types are represented by Class objects. However, with generics, Some types cannot be represented by Class objects, such as ArrayList < string >, ArrayList <? > Wait, JDK Types such as Type interface are added to represent various types with generics. Type It is a common high-level interface of all types in the Java programming language. They include primitive types, parameterized types, array types, type variables, and primitive types. Type The implementation classes include Class and some sub interfaces: genericarraytype, parameterizedtype, TypeVariable < d >, wildcardtype GenericArrayType: Represents T [] generic array ParameterizedType: Represents the ArrayList < string > parameterized type TypeVariable<D>: Represents generic types such as T WildcardType: Represents the generic type ArrayList with wildcards <? >, Arraylist<? Extensions upper limit >, ArrayList <? Super lower limit > Father<String,Integer>Is a ParameterizedType parameterized type */ ParameterizedType pt = (ParameterizedType) genericSuperclass;//The downward transformation is to call the getActualTypeArguments method of the sub interface Type[] actualTypeArguments = pt.getActualTypeArguments();//Get the specific type parameter of the generic, that is, the specific type in < > for (Type actualTypeArgument : actualTypeArguments) { System.out.println(actualTypeArgument); } System.out.println("-------------------------"); Type[] genericInterfaces = clazz.getGenericInterfaces(); for (Type genericInterface : genericInterfaces) { if(genericInterface instanceof ParameterizedType){ ParameterizedType p = (ParameterizedType) genericInterface; Type[] arr = p.getActualTypeArguments(); System.out.println(Arrays.toString(arr)); } } } } class Father<T,U>{ } class Sub extends Father<ArrayList<String>,Integer> implements Comparable<Sub>, Serializable { @Override public int compareTo(Sub o) { return 0; } }
6. Get information about inner and outer classes
Demonstrates how to get the inner class information of the Outer class
Class:
Class<?>[] Getclasses (): get all public internal classes and internal interfaces
Class<?>[] getDeclaredClasses() : Get all declared inner classes and inner interfaces
Class<?> Getenclosingclass(): get the information of external class or external interface
public class TestInnerOuter { public static void main(String[] args) { //Step 1: get the Class object of Outer Class Class clazz = Outer.class; //Step 2: get its internal class information Class[] arr = clazz.getDeclaredClasses(); for (Class c : arr) { System.out.println(c); } System.out.println("-----------------------"); //Get all inner classes of HashMap Class hashMapClass = HashMap.class; //Get the inner class of HashMap Class[] declaredClasses = hashMapClass.getDeclaredClasses(); for (Class declaredClass : declaredClasses) { System.out.println(declaredClass); } System.out.println("------------------------"); //Demonstrates how to get the external class information of the Inner class //Step 1: get the Class object of Inner Class innerClass = Outer.Inner.class; //Step 2: get the new external class Class enclosingClass = innerClass.getEnclosingClass(); System.out.println(enclosingClass); System.out.println("------------------------"); List<Integer> list = Arrays.asList(1, 2, 3, 4); Class<? extends List> listClass = list.getClass(); Class<?> c = listClass.getEnclosingClass(); System.out.println("listClass=" + listClass); System.out.println("listClass External class for=" + c); } } class Outer{ class Inner{ } static class NeiClass{ } }
7. Reflection operation array
Under the java.lang.reflect package, the Array class provides methods for dynamically creating and accessing Java arrays.
static Object newInstance(Class<?> componentType, int length)
Class<?> Componenttype: the type of array element
int length: the length of the array
public class TestArray { public static void main(String[] args) { MyArrayList<String> list = new MyArrayList<>(String.class,5); list.add("hello"); list.add("world"); list.add("java"); list.add("mysql"); list.add("atguigu"); list.add("chai"); String str = list.get(1); System.out.println(str); } @Test public void test(){ Object arr = Array.newInstance(int.class, 5); Array.set(arr,0,10); Array.set(arr,1,20); System.out.println(Array.get(arr,0)); System.out.println(Array.get(arr,1)); System.out.println(Array.get(arr,2)); } }
import java.lang.reflect.Array; import java.util.Arrays; public class MyArrayList<T> { private T[] arr; private int total; public MyArrayList(Class tClassType,int length){ arr = (T[]) Array.newInstance(tClassType, 5); } public void add(T element){ if(total>=arr.length){ arr = Arrays.copyOf(arr, arr.length*2); } arr[total++] = element; } public T get(int index){ return arr[index]; } }
8. Reflection works with custom annotations
(1) Custom annotation
Syntax format:
[modifier] @ interface annotation name{
}
Syntax format:
[modifier] @ interface annotation name{
Abstract methods;
}
Syntax format:
[modifier] @ interface annotation name{
Return value type method name () Default default return value;
}
Note: there are requirements for return value types. There are 8 basic data types, String type, Class type, annotation type, or their arrays. Other types are not allowed
(2) Use custom annotations
If the annotation used does not have an abstract method, or the abstract method has a default return value, you do not need to specify the return value for the abstract method when using the annotation
Otherwise, if the annotation used has an abstract method and the abstract method does not specify a default return value, you must specify a return value for the non abstract method in () after the annotation name.
Note: if the abstract method name is value, value = can be omitted when specifying the return value of the method when using annotations.
However, if the method name is another word or there are multiple abstract methods, it cannot be omitted Method name=
(3) Take a look at the system annotation declaration
@Override: java.lang package
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
// There are no abstract methods
}
@SuppressWarnings
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
String[] value(); // Abstract method
}
(4) Meta annotation
The annotation added to the annotation is called meta annotation.
There are four meta annotations:
@Target: indicates where the annotation is used
Its location is specified by the 10 constant objects of the ElementType enumeration class
@Retention: indicates the lifecycle of the annotation
Its life cycle is specified by three constant objects of the RetentionPolicy enumeration class
Source (source code)
Class (bytecode)
RUNTIME Only annotations that live to RUNTIME can be read by reflection.
@Documented: whether the annotation can be recognized by javadoc.exe and read into the API document
@Inherited: can it be inherited by subclasses
public class TestAnnotation { @SuppressWarnings(value="unused") public static void main(String[] args) { int a = 1; //Try to get the annotation above the MyClass class //Step 1: get the Class object of MyClass Class first Class clazz = MyClass.class; //Step 2: get the annotation on the class Annotation[] annotations = clazz.getAnnotations(); for (Annotation annotation : annotations) { System.out.println(annotation); if(annotation instanceof MyAnnotation){ MyAnnotation my = (MyAnnotation) annotation;//Transition down to call the abstract method declared in MyAnnotation System.out.println(my.info()); System.out.println(my.value()); } } System.out.println("------------------------"); //Demonstrate that the MySub subclass inherits the MyAnnotation annotation annotation of the parent class Class<MySub> mySubClass = MySub.class; System.out.println(mySubClass.getAnnotation(MyAnnotation.class)); } } @Retention(RetentionPolicy.RUNTIME) @Inherited //Can be inherited by subclasses @interface MyAnnotation{ String value(); String info() default "atguigu"; } @interface OtherAnnotation{ } @OtherAnnotation @MyAnnotation(value="Shang Silicon Valley",info="Beijing Shangshan Silicon Valley") class MyClass{ } class MySub extends MyClass{ } class Base{ public void method(){ System.out.println("Method of parent class"); } } class Son extends Base{ @Override //Because the Override annotation has no abstract method, you can directly use @ Override without adding (), specifying the return value of the abstract method public void method() { super.method(); } }