Create and use a Class object, and create a class Object
Class and Class Object
A Class is a part of a program. Each Class has a Class object, that is, a Class object is generated every time a new Class is compiled and compiled. When the program creates the first reference to a static member of the class, it dynamically loads the class into the JVM. This shows that the class constructor is also a static method, even if the static keyword is not used before the constructor. Therefore, the java program is not fully loaded before running. Each Class only loads the Class object of this Class into the memory when necessary. This Class object is used to create all objects of this Class. The following code proves the above content:
class Demo1 { static int i; static { System.out.println("loading Demo1"); }}class Demo2 { static { System.out.println("loading Demo2"); }}class Demo3 { static { System.out.println("loading Demo3"); }}class TestDemo { public static void main(String[] args) { int i = Demo1.i; try { Class.forName("Demo2"); } catch (ClassNotFoundException e) { System.out.println("couldn't find Demo2"); } new Demo3(); } /* output * loading Demo1 * loading Demo2 * loading Demo3 */}
Among them, static {} is a static block and will be executed when the class is loaded. The first output is that we loaded the Demo1 class with the static member I in Demo1, in the second output, we call a static method forName of the Class. The parameter is the name of a Class and the Class Object of the Class name is returned, this method also serves to load the class if it is not loaded. When the new keyword is used to create an object, the class constructor is called, and the class is loaded and the third row is output.
Create a Class Object
If we want to obtain the type information of a Class during running, we must first obtain the Class Object of the Class. There are three methods to obtain the Class Object:
- Class. forName: a static method of the Class, passed in the Class's full name
- Object. getClass: the method of the root Class Object. The Class Object of the Class of the Object is returned.
- Class Name. class: This method is also called a class literal constant. This method is not only simple, but also safer, because it can be checked during compilation.
class Demo1 { static final int i1 = 47; static final int i2 = (int)(Math.random() * 10000); static { System.out.println("loading Demo1"); }}class TestDemo { public static void main(String[] args) { Class<Demo1> demo1Class = Demo1.class; System.out.println("after Demo1.class"); int i = Demo1.i1; System.out.println("after Demo1.i1"); i = Demo1.i2; System.out.println("after Demo1.i2"); } /* output * after Demo1.class * after Demo1.i1 * loading Demo1 * after Demo1.i2 */}
From the code above, you will find that the class is not loaded by using the Class name. Class method, because using this method to create a class object will not automatically initialize this Class object. When we use a Class, we can actually divide it into three steps: 1) loading, which is executed by the Class loader, that is, creating a Class object through the byte code found. 2) link to verify the bytecode in the class, allocate storage space for the static domain, and parse references to other classes. 3) initialize the class. If the class has a parent class, initialize it and execute the static initialization tool and static block. The three steps show that the static block is executed only when the Class object is initialized. Then we call the i1 of Demo1 to execute static blocks, because static final modifies a constant in the compilation period. classes that are not needed to initialize when we read this value are called, it does not mean that the class will not be initialized when the accessed domain is modified by static final. We can see from calling i2 that the i2 value is not a constant of the compiler.
Use of Class objects
The Class Object provides a large number of methods for us to obtain the attributes and methods of the Class. We can also use the Class object to create Class instances, modify attribute values, and execute methods, the following are common methods for Class objects:
- GetFields: Get all the attributes modified by public, and return a Field array (including the parent class)
- GetDeclaredFields: obtains all attributes and returns an array of fields.
- GetField: input a parameter (attribute name) to obtain a single attribute. A Field object is returned and only public-modified
- GetDeclaredField: input a parameter (attribute name) to obtain a single attribute. A Field object is returned.
Public class Demo {public int field1; private String field2; public void method1 (Integer arg0) {System. out. println ("execute method1");} private String method1 () {return null;} class TestDemo {public static void main (String [] args) throws Exception {Class <Demo> demoClass = Demo. class; Field [] fields1 = demoClass. getFields (); Field [] fields2 = demoClass. getDeclaredFields (); System. out. println (Arrays. toString (fields1); System. out. println (Arrays. toString (fields2); Field field1 = demoClass. getField ("field1"); // Field field2 = demoClass. getField ("field2"); // throwing an exception during runtime Field field3 = demoClass. getDeclaredField ("field2"); System. out. println (field1); System. out. println (field3);}/* output * [public int Demo. field1] * [public int Demo. field1, private java. lang. string Demo. field2] * public int Demo. field1 * private java. lang. string Demo. field2 */}
- GetMethods: Get all public modifier methods, including the parent class, and return the Method array.
- GetDeclaredMethods: Get all the returned results, excluding the parent class. Return the Method array.
- GetMethod: input a parameter (Method name) and return a Method object. Only public-modified
- GetDeclared: input a parameter (Method name) and return a Method object.
Class TestDemo {public static void main (String [] args) throws Exception {Class <Demo> demoClass = Demo. class; // Demo class Method [] methods1 = demoClass. getMethods (); Method [] methods2 = demoClass. getDeclaredMethods (); System. out. println (Arrays. toString (methods1); System. out. println (Arrays. toString (methods2); Method method1 = demoClass. getMethod ("method1", new Class [] {Integer. class}); // Method method2 = demoClass. getMethod ("method2"); Method method3 = demoClass. getDeclaredMethod ("method2"); System. out. println (method1); System. out. println (method3);}/*** [public void Demo. method1 (java. lang. integer), public final void java. lang. object. wait () throws java. lang. interruptedException ,... * [public void Demo. method1 (java. lang. integer), private java. lang. string Demo. method2 ()] * public void Demo. method1 (java. lang. integer) * private java. lang. string Demo. method2 ()*/}
- NewInstance: creates an instance of this type.
Class TestDemo {public static void main (String [] args) throws Exception {Class <Demo> demoClass = Demo. class; Demo demo = demoClass. newInstance (); Field field2 = demoClass. getDeclaredField ("field2"); field2.setAccessible (true); field2.set (demo, "setField2"); System. out. println (field2.get (demo); Method method1 = demoClass. getMethod ("method1", Integer. class); method1.invoke (demo, new Object [] {11});}/*** setField2 * execute method1 */}
The code above shows that creating an instance of the class is not only created by using the new keyword, but also using the Field object method to obtain the attribute value of an instance. In addition, you will find that using the Field object method can even change the private attribute value of an instance. To change the private property value, you must call the setAccessible method and pass in "true" (default value: false ). The Method object Method is used later to execute the instance Method, and the input parameters are the parameter arrays of the instance and Method respectively. If the setAccessible Method of Method is called and true is passed in, the private method of the instance can be executed. At this point, you may wonder if there is any way to prevent us from calling Private attributes through reflection (that is, the Field and Method methods, you can try to put the property value in a private internal class or put it in an anonymous class. In the end, you will find that this will not block reflection calls. However, we can use final to modify an attribute. Even if we can perform the modification operation, it does not actually change the attribute value.