Learn more about Java basics


Understand Class objects in depth

RRIT and the concept of Class objects

RRIT (Run-time Type Identification) Runtime Type Identification. As mentioned in Chapter 14 of Thinking in Java, it is used to identify an object’s type and class information at runtime. There are two main approaches: “traditional” RTTI, which assumes that all types are known at compile time; The other is a “reflection” mechanism that allows us to discover and use information about a class at run time.

Classes are part of a program, and each class has a class object. In other words, every time a new Class is written and compiled, a Class object is generated (more properly, stored in a.class file of the same name). All classes are dynamically loaded into the JVM the first time they are used. For example, if we write a Test class and compile it to test. class, the class object of our Test class is stored in the class file. When we create a new object or reference a static member variable, the Class loader subsystem in the Java Virtual Machine (JVM) loads the corresponding Class object into the JVM, and the JVM then creates an instance object from the Class object associated with this type information or provides a reference value for the static variable. It is important to note that for every class class written manually, no matter how many instance objects are created, there is only one class object in the JVM, that is, there is only one corresponding class object in memory for each class.

Test t1 = new Test();
Test t2 = new Test();
Test t3 = new Test();
Copy the code

As shown above, there is actually only one Test Class object in the JVM memory.

The Class Class, which is also a real Class, exists in the JAVa.lang package of the JDK. An instance of a Class Class represents the Class enum or interface and annotation of the Java application runtime. (Each Java Class runtime is represented in the JVM as a Class object, The class object can be obtained by the methods.class, type.getClass (), class.forname (” class name “), etc. Arrays are also mapped as a class object, which is shared by all arrays with the same element type and dimension. The basic types Boolean, byte, char, short, int, long, float, double, and the keyword void also represent class objects.

public final class Class<T> implements java.io.Serializable, GenericDeclaration, Type, AnnotatedElement { private static final int ANNOTATION= 0x00002000; private static final int ENUM = 0x00004000; private static final int SYNTHETIC = 0x00001000; private static native void registerNatives(); static { registerNatives(); } /* * Private constructor. Only the Java Virtual Machine creates Class objects. * This constructor is not used and prevents the default constructor being * generated. */ private Class(ClassLoader loader) { // Initialize final fieldforclassLoader. The initialization value of non-null // prevents future JIT optimizations from assuming this final field is  null. classLoader = loader; }Copy the code

At this point, we can get the following information:

  • The Class Class is a Class, not the same as the Class keyword.

  • Manually written classes are compiled to produce a Class object that represents the type information of the created Class and is stored in a file with the same name (bytecode file).

  • Each class identified by the keyword class has one and only one corresponding class object in memory to describe its type information. No matter how many instances are created, a class object is used.

  • Class classes have only private constructors, so the corresponding Class object can only be created and loaded by the JVM

  • The object of the Class Class is to provide or obtain information about the type of an object at runtime, which is important for reflection techniques (more on reflection later).

Class object loading and fetching

Load the Class object

As we mentioned earlier, Class objects are loaded by the JVM, so when are they loaded? Virtually all classes are dynamically loaded into the JVM when they are first used. When the program creates the first static member reference to a class, the used class is loaded (in effect, the bytecode file for that class is loaded). Using the new operator to create a new instance object of a class is also treated as a reference to a static member of the class. (Constructors are also static methods of the class.) So Java programs are not fully loaded into memory before they start running. The Class loader first checks to see if the Class object has been loaded. If it has not been loaded, the default Class loader looks for the.class file by name. When the class’s bytecode files are loaded, they must be verified to ensure that they are not corrupted and contain no bad Java code (which is detected by Java’s security mechanism), and then loaded dynamically into memory without any problems. The equivalent Class object is then loaded into memory (that’s what the.class bytecode files hold, after all) and can be used to create all instances of the Class.

Class loading process: 1. The load in the loading stage, the virtual machine needs to be done three things: (1) through a fully qualified class name (org/fenixsoft/clazz/TestClass) access to define such binary byte stream (. Class files); (2) Transform the static storage structure represented by this byte stream into the runtime data structure of the method area; (3) Generate a java.lang.Class object representing this Class in memory, which acts as an access point for various data of this Class in the method area; 2. The validation stage is very important. Whether this stage is rigorous or not directly determines whether the Java VIRTUAL machine can withstand malicious code attacks. The verification phase basically completes the following four verification actions: (1) File format verification Verifies whether the byte stream conforms to the Class file format specification and can be processed by the vm of the current version; The verification in this stage is based on binary byte stream. Only after passing the verification in this stage, the byte stream will enter the method area of memory for storage. Therefore, the following three verification stages are based on the storage structure of the method area, and will not operate the byte stream directly. (2) Metadata verification carries out semantic analysis on the information described by bytecode to ensure that the information described conforms to the requirements of Java language specifications and that there is no metadata information that does not conform to the Requirements of Java language specifications; (3) Bytecode verification through data flow and control flow analysis, to determine the semantics of the program is legal and logical, to ensure that the verified method will not harm the security of virtual machine events during operation; (4) Symbolic reference verification can be regarded as the matching verification of information outside the class itself (various symbolic references in the constant pool) to ensure the normal execution of parsing actions; 3. Preparation The preparation phase is to formally allocate memory for class variables and set their initial values. The memory used by these variables will be allocated in the method area. Only class variables (static modified variables) are allocated, not instance variables, which are allocated in the Java heap along with the object when it is instantiated; 4. The parsing phase is the process in which the VIRTUAL machine replaces symbolic references in the constant pool with direct references. The parse action is mainly for class or interface, field, class method, method type, method handle and call point qualifier 7 class symbol references. Initialization is when you actually start executing the Java program code (or bytecode) defined in the class. How initialization is triggered: (1) When new, getstatic, putstatic or involestatic instructions are encountered; (2) when a java.lang.reflect method is used to make a reflection call to a class; (3) When initializing a class, if the parent class has not been initialized, the initialization of the parent class will be triggered first; (4) When the VM starts, the user needs to specify a main class (the class containing the main() method) to execute. The VM initializes this main class first. (5) if a Java. Lang. Invoke the final analytical result is REF_getStatic, REF_putStatic MethodHandle instance, REF_invokeStatic method handles, if the handle of the time a class initialization, Initialize it;

The above is derived from the book “Deep Understanding of the Java Virtual Machine”, you can go to read, this book is basically a Java program ape learning one of the must-read. I won’t go into that here, because this is another JVM domain. If I write about it in the future, I’ll post it here.

Get the Class object

There are three main types of Class object fetching:

  • Get this from the instance getClass () method
  • Class. ForName method
  • Class literal constants get

Get this from the instance getClass () method

    Test t1 = new Test();
    Class clazz=test.getClass();
    System.out.println("clazz:"+clazz.getName());
Copy the code

GetClass (), inherited from the top-level Object Class, returns a Class Object reference representing the actual type of the Object.

Class. ForName method

Clazz = class.forname (clazz= class.forname)"com.hiway.Test");
      System.out.println("clazz:"+clazz.getName());
    }catch (ClassNotFoundException e){
      e.printStackTrace();
    }
Copy the code

The forName method is a static member of the Class. Remember that all Class objects derive from this Class, so methods defined in the Class will apply to all Class objects. Using the forName method, we can get the reference to the corresponding Class object of the Test Class. Note that the forName method needs to catch an exception named ClassNotFoundException, because the forName method does not detect the existence of the corresponding class (or.class file) for the string it passes. If not, a ClassNotFoundException is thrown.

Using the forName method triggers class initialization, as opposed to using class literal constants for fetching

Class literal constants get

Clazz = test.class;Copy the code

This is not only simpler, but also safer, because it is checked at compile time (and therefore does not need to be placed in a try block). And it eliminates calls to the forName() method, so it’s also more efficient. It is interesting to note that when a reference to a class object is created using “.class “, the class object is not automatically initialized. The preparation for using the class actually consists of three steps:

  1. Load, which is performed by the Class loader, looks for bytecodes (usually in the path specified by the classpath, but not required) and creates a Class object from them.
  2. Link. The bytecode in the class is validated during the linking phase, storage space is distributed for static fields, and all references to other classes created by this class are resolved, if necessary.
  3. Initialization. If the class has a superclass, it is initialized, performing a static initializer and a static initialization block.
class Initable{
     static final int staticFinal = 47;
     static final int staticFinal2 = ClassInitialization.rand.nextInt(1000);
     static {
          System.out.ptintln("Initializing Initable");
     }
}

class Initable2 {
     static int staticNonFinal = 147;
     static {
          System.out.println("Initializing Initable2");
     }
}

class Initable3 {
     static int staticNonFinal = 74;
     static {
          System.out.println("Initializing Initable3");
     }
}

public class ClassInitialization {
     public static Random rand = new Random(47);
     public static void main(String[] args) throws Exception {
          Class initable = Initable.class;
          System.out.println("After creating Initable ref");
          System.out.println(Initable.staticFinal);
          System.out.println(Initable.staticFinal2);
          System.out.println(Initable2.staticNonFinal);
          Clas initable3 = Class.forName("Initable3");
          System.out.println("After creating Initable3 ref"); System.out.println(Initable3.staticNonFinal); } } /* output After creating Initable ref 47 Initializing Initable 258 Initializing Initable2 147 Initializing Initable3  After creating Initable ref 74Copy the code

If a static final value is a compiler constant, as Initable. StaticFinal is, it can be read without initializing the Initable class. However, simply making a field static and final is not enough to ensure this behavior; for example, access to initable. staticFinal2 will force initialization of the class because it is not a compile-time constant.

If a static field is not final, access to it always requires linking (allocating storage for the field) and initializing (initializing the storage) before it can be read, as seen in the access to initable2.Staticnonfinal. Fetching the Class object of Initable Class by literal constants does not trigger initialization of Initable Class, which is verified by the above analysis. The call to Initable. StaticFinal does not trigger initialization. This is because staticFinal is a compile-time static constant, which is stored ina constant pool called NotInitialization by constant propagation optimization for Initable classes. References to the constant staticFinal of Ininitialization are converted into references to the NotInitialization constant pool. Therefore, after compile time, references to compile-time constants will be obtained from the NotInitialization constant pool. This is why referring to compile-time static constants does not trigger initialization of Initable classes. However, after Initable. StaticFinal2 is called, Initable class initialization is triggered. Note that staticFinal2 is static and final, but its value is not determined at compile time, so staticFinal2 is not a compile time constant. To use this variable, you must first initialize the Initable class. Initable2 and Initable3 classes are static member variables that are not compile-time constants, and references to them trigger initialization. As for the forName method fetching the Class object, initialization must be triggered, as discussed earlier.

Equivalence between instanceof and Class

In the case of the instanceof keyword, it returns a Boolean value intended to tell us whether the object is an instanceof a particular type. Use instanceof to check if obj is an instanceof Animal before casting. If true is returned before casting, this will avoid throwing a ClassCastException.

public void cast2(Object obj){
    if(obj instanceof Animal){ Animal animal= (Animal) obj; }}Copy the code

The isInstance method is a Native method of the Class, and is also used to determine the type of an object.

Public void cast2(Object obj){//instanceof keywordif(obj instanceof Animal){ Animal animal= (Animal) obj; } / / isInstance methodif(Animal.class.isInstance(obj)){ Animal animal= (Animal) obj; }}Copy the code

In fact, the instanceOf and isInstance methods produce the same result.

class A {}

class B extends A {}

public class C {
  static void test(Object x) {
    print("Testing x of type " + x.getClass());
    print("x instanceof A " + (x instanceof A));
    print("x instanceof B "+ (x instanceof B));
    print("A.isInstance(x) "+ A.class.isInstance(x));
    print("B.isInstance(x) " +
      B.class.isInstance(x));
    print("x.getClass() == A.class " +
      (x.getClass() == A.class));
    print("x.getClass() == B.class " +
      (x.getClass() == B.class));
    print("x.getClass().equals(A.class)) "+
      (x.getClass().equals(A.class)));
    print("x.getClass().equals(B.class)) " +
      (x.getClass().equals(B.class)));
  }
  public static void main(String[] args) {
    test(new A());
    test(new B());
  } 
}

/* output
Testing x of type class com.zejian.A
x instanceof A true
x instanceof B false// The parent class is not necessarily a type of the subclass.true
B.isInstance(x) false
x.getClass() == A.class true
x.getClass() == B.class false
x.getClass().equals(A.class)) true
x.getClass().equals(B.class)) false
---------------------------------------------
Testing x of type class com.zejian.B
x instanceof A true
x instanceof B true
A.isInstance(x) true
B.isInstance(x) true
x.getClass() == A.class false
x.getClass() == B.class true
x.getClass().equals(A.class)) false
x.getClass().equals(B.class)) true
Copy the code

reflection

Reflection mechanism is in the running state, for any class, can know all the attributes and methods of the class; For any object, any of its methods and attributes can be called, this dynamic information and dynamic call object method function is called the Reflection mechanism of the Java language. Reflection has always been the shining light in Java, and it is the backbone of most frameworks currently implemented (Spring/Mybatis, etc.). In Java, the Class Class provides full support for reflection along with the java.lang.Reflect Class library. The Constructor Class represents the Constructor of a Class object. It can be used to dynamically create objects at runtime. Field represents the member variables of a Class object. It allows you to dynamically change the value of a member variable (including private) at run time. Method represents the member Method of a Class object. It allows you to dynamically call the Method of an object (including private).

The Constructor class and its usage

The Constructor Class exists in the reflection package (java.lang.Reflect) and reflects the Class Constructor represented by the Class object. The Constructor object is obtained through methods in the Class Class. The main Constructor related methods of the Class are as follows:

Method return value Method names Method statement
static Class<? > forName(String className) Returns the Class object associated with the Class or interface with the given string name.
Constructor getConstructor(Class<? >… parameterTypes) Returns a constructor object with public access for the specified argument type
Constructor<? > [] getConstructors() Returns an array of Constructor objects for all constructors that have public access
Constructor getDeclaredConstructor(Class<? >… parameterTypes) Returns constructor objects of the specified parameter type, all declared (including private)
Constructor<? > [] getDeclaredConstructor() Returns all declared (including private) constructor objects
T newInstance() Call the no-argument constructor to create a new instance of the Class represented by this Class object.

Let’s look at a simple example to understand the use of the Constructor object:

public class ConstructionTest implements Serializable { public static void main(String[] args) throws Exception { Class<? > clazz = null; Clazz = class.forname (clazz = class.forname ("com.example.javabase.User"); // Instantiate the default constructor, User must have no arguments to the constructor, otherwise exception User User = (User) clazz.newinstance (); user.setAge(20); user.setName("Jack");
        System.out.println(user);

        System.out.println("-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -"); Constructor cs1 = clazz.getconstructor (string.class); // Constructor cs1 = clazz.getconstructor (String. // Create User User user1= (User) cs1.newinstance ("hiway");
        user1.setAge(22);
        System.out.println("user1:"+user1.toString());

        System.out.println("-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -"); / / specified int and String Constructor parameters, the method is private construction private Constructor cs2. = clazz getDeclaredConstructor (int. Class, String. Class); // Since it is private, cs2.setaccessible (true); User user2= (user) cs2.newInstance(25,"hiway2");
        System.out.println("user2:"+user2.toString());

        System.out.println("-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -"); // Get all constructs including private Constructor<? > cons[] = clazz.getDeclaredConstructors(); // View the parameters required by each constructorfor(int i = 0; i < cons.length; I++) {// get the constructor argument type Class<? > clazzs[] = cons[i].getParameterTypes(); System.out.println("Constructor ["+i+"]:"+cons[i].toString() );
            System.out.print("Parameter type ["+i+"] : (");
            for (int j = 0; j < clazzs.length; j++) {
                if (j == clazzs.length - 1)
                    System.out.print(clazzs[j].getName());
                else
                    System.out.print(clazzs[j].getName() + ",");
            }
            System.out.println(")");
        }
    }
}


class User {
    private int age;
    private String name;
    public User() { super(); } public User(String name) { super(); this.name = name; } /** * private construct * @param age * @param name */ private User(int age, String name) {super(); this.age = age; this.name = name; } public intgetAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "User{" +
                "age=" + age +
                ", name='" + name + '\''+'}'; } } /* output User{age=20, name='Jack'}
--------------------------------------------
user1:User{age=22, name='hiway'}
--------------------------------------------
user2:User{age=25, name='hiway2'} -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- the constructor [0] : private com. Example. Javabase. The User (int, Java. Lang. String) Parameter types [0] : (int, Java. Lang. String) constructor [1] : public com. Example. Javabase. The User (Java. Lang. String) parameter types. [1] : (Java lang. String) The constructor [2] : public com. Example. Javabase. User () parameter types [2] : ()Copy the code

Some common methods for the Constructor class itself are as follows (only partially; other apis are available)

Method return value Method names Method statement
Class getDeclaringClass() Returns a Class object representing the Class that declares the Constructor represented by this Constructor object, which in essence returns the true type (no arguments)
Type[] getGenericParameterTypes() Return a set of Type objects in declarative order, which return the parameter types of the Constructor object Constructor.
String getName() Returns the name of this constructor as a string.
Class<? > [] getParameterTypes() Return a set of Class objects in declarative order, that is, the parameter types of the Constructor represented by the Constructor object
T newInstance(Object… initargs) Use the Constructor represented by this Constructor object to create a new instance
String toGenericString() Returns a string describing this Constructor, including type parameters.

The code is shown as follows:

        Constructor cs3 = clazz.getDeclaredConstructor(int.class,String.class);
        System.out.println("-----getDeclaringClass-----"); Class uclazz=cs3.getDeclaringClass(); // The Constructor object represents the Constructor class system.out.println ("Constructor class :"+uclazz.getName());

        System.out.println("-----getGenericParameterTypes-----"); / / object represents the Constructor object represented by the method of parameter Type Type [] TPS = cs3. GetGenericParameterTypes ();for (Type tp:tps) {
            System.out.println("Parameter tp:"+tp);
        }
        System.out.println("-----getParameterTypes-----"); // Get the constructor argument type Class<? > clazzs[] = cs3.getParameterTypes();for (Class claz:clazzs) {
            System.out.println("Parameter Name :"+claz.getName());
        }
        System.out.println("-----getName-----"); // Return the name of this constructor as a string system.out.println ("getName:"+cs3.getName());

        System.out.println("-----getoGenericString-----"); // Returns a string describing this Constructor, including type parameters. System.out.println("getoGenericString():"+cs3.toGenericString()); / * the output -- -- -- -- -- getDeclaringClass -- -- -- -- -- the class constructor: com. Example. Javabase. User -- -- -- -- -- getGenericParameterTypes -- -- -- -- -- the parameter name tp: int Parameter name TP :class java.lang.String -----getParameterTypes----- Parameter name :int Parameter name :java.lang.String -----getName----- getName:com.example.javabase.User -----getoGenericString----- getoGenericString():private com.example.javabase.User(int,java.lang.String)Copy the code

The Field class and its usage

Field provides information about a single Field of a class or interface and dynamic access to it. The reflected field may be a class (static) field or an instance field. In the same way, we can obtain the Field object representing the Field information by using the methods provided by the Class Class.

Method return value Method names Method statement
Field getDeclaredField(String name) Gets the (including private) field of the specified name, excluding inherited fields
Field[] getDeclaredField() Gets all (including private) fields of the Class or interface represented by the Class object, excluding inherited fields
Field getField(String name) Gets a public decorated field with the specified name, including inherited fields
Field[] getField() Gets the field whose modifier is public, containing the inherited field

The following code demonstrates the use of the above method

public class ReflectField { public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException { Class<? > clazz = Class.forName("reflect.Student"); Field = clazz.getField(); // Public Field = clazz.getfield ()"age");
        System.out.println("field:"+field); Field fields[] = clazz.getFields(); Field fields[] = clazz.getFields();for (Field f:fields) {
            System.out.println("f:"+f.getDeclaringClass());
        }

        System.out.println("================getDeclaredFields===================="); Field fields2[] = clazz.getDeclaredFields(); clazz.getDeclaredFields();for (Field f:fields2) {
            System.out.println("f2:"+f.getDeclaringClass()); Clazz.getdeclaredfield (clazz.getDeclaredField(clazz.getDeclaredField));"desc");
        System.out.println("field2:"+field2); } /** Output: field:public int reflect.Person.age f:public java.lang.String reflect.Student.desc f:public int reflect.Person.age f:public java.lang.String reflect.Person.name ================getDeclaredFields==================== f2:public java.lang.String reflect.Student.desc f2:private int reflect.Student.score field2:public java.lang.String reflect.Student.desc */ } class Person{ public int age; public String name; / / to omitsetClass Student extends Person{public String desc; private int score; / / to omitsetAnd get methods}Copy the code

The above method is important to note that if we don’t expect to obtain its parent Class field, use Class Class getDeclaredField/getDeclaredFields method to get the fields, field joint access to the parent Class, if you need it Use Class getField/getFields, but only public fields can be retrieved, not private fields from the parent. The following assigns the specified class attribute using the Field class’s own method, as shown in the following code:

// Get the Class object reference Class<? > clazz = Class.forName("reflect.Student"); Student st= (Student) clazz.newInstance(); Field ageField = clazz.getField("age");
ageField.set(st,18);
Field nameField = clazz.getField("name");
nameField.set(st,"Lily"); Field descField = clazz.getDeclaredField(clazz.getDeclaredField)"desc");
descField.set(st,"I am student");
Field scoreField = clazz.getDeclaredField("score"); // setAccessible, score is private scorefield.setaccessible (true); scoreField.set(st,88); System.out.println(st.toString()); Student{age=18, name='Lily ,desc='I am student', score=88} system.out.println (scorefield.get (st)); / / 88Copy the code

The set(Object obj, Object value) method is the method of the Field class itself, used to set the value of the Field, and get(Object obj) is to get the value of the Field.

Method return value Method names Method statement
void set(Object obj, Object value) Sets the Field represented by this Field object on the specified object variable to the specified new value.
Object get(Object obj) Returns the value of the Field represented by this Field on the specified object
Class<? > getType() Returns a Class object that identifies the declared type of the Field represented by the Field object.
boolean isEnumConstant() Returns true if this field represents an element of enumerated type; Otherwise return false
String toGenericString() Returns a string that describes the Field, including its generic type
String getName() Returns the name of the Field represented by this Field object
Class<? > getDeclaringClass() Returns a Class object representing a Class or interface that declares the fields represented by this Field object
void setAccessible(boolean flag) Set the accessible flag of this object to the indicated Boolean value, that is, to make it accessible

In fact, the Field class also provides methods for setting values for basic data types, such as setInt()/getInt(), setBoolean()/getBoolean, setChar()/getChar(), and so on. I’m not going to list all of them here, just refer to the API documentation if necessary. It is important to note that the Field Field decorated with the final keyword is safe and can receive any changes at run time, but its actual value will not change as a result.

Method class and its usage

Methods provide information about a single Method on a class or interface (and how to access that Method), which may be a class Method or instance Method (including abstract methods). The Class gets the methods associated with the Method object:

Method return value Method names Method statement
Method getDeclaredMethod(String name, Class<? >… parameterTypes) Returns a Method object with the specified argument that reflects the specified declared Method of the Class or interface represented by this Class object.
Method[] getDeclaredMethod() Returns an array of Method objects that reflect all methods declared by the Class or interface represented by this Class object, including public, protected, default (package) access, and private methods, but not inherited methods.
Method getMethod(String name, Class<? >… parameterTypes) Returns a Method object that reflects the specified public member methods of the Class or interface represented by this Class object.
Method[] getMethods() Returns an array of Method objects that reflect the public member methods of the Class or interface represented by this Class object (including those declared by the Class or interface and those inherited from superclasses and superinterfaces).

The above methods are also demonstrated by examples:

import java.lang.reflect.Method;

public class ReflectMethod  {


    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {

        Class clazz = Class.forName("reflect.Circle"); Method = clazz.getMethod(clazz.getMethod);"draw",int.class,String.class);

        System.out.println("method:"+method); [] methods = clazz.getmethods ();for (Method m:methods){
            System.out.println("m::"+m);
        }

        System.out.println("= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = ="); Method 1 = clazz.getDeclaredMethod(clazz.getDeclaredMethod);"drawCircle");
        System.out.println("method1::"+method1); [] methods1=clazz.getDeclaredMethods(); clazz.getDeclaredMethods();for (Method m:methods1){
            System.out.println("m1::"+m); }} /** Output: method:public void reflect.Shape.draw(int,java.lang.String) m::public int reflect.Circle.getAllCount() m::public void reflect.Shape.draw() m::public void reflect.Shape.draw(int,java.lang.String) m::public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException m::public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException m::public final void java.lang.Object.wait() throws java.lang.InterruptedException m::public boolean java.lang.Object.equals(java.lang.Object) m::public java.lang.String java.lang.Object.toString() m::public native int java.lang.Object.hashCode() m::public final native java.lang.Class java.lang.Object.getClass() m::public final native void java.lang.Object.notify() m::public final native void java.lang.Object.notifyAll() ========================================= method1::private void reflect.Circle.drawCircle()  m1::public int reflect.Circle.getAllCount() m1::private void reflect.Circle.drawCircle() */ } class Shape { public voiddraw(){
        System.out.println("draw");
    }

    public void draw(int count , String name){
        System.out.println("draw "+ name +",count="+count);
    }

}
class Circle extends Shape{

    private void drawCircle(){
        System.out.println("drawCircle");
    }
    public int getAllCount() {return100; }}Copy the code

When we use getMethods to getMethod objects, we will also get the methods of the parent class. As shown in the above output, the methods of the Object class are printed. While the getDeclaredMethod/getDeclaredMethods method can only obtain the current class. We can choose according to the situation when using. The following shows how to call a Method of a given class through the Method object:

Class clazz = Class.forName("reflect.Circle"); // Create an object Circle Circle = (Circle) clazz.newinstance (); Method = clazz.getMethod()"draw",int.class,String.class); // Invoke Method (Object obj,Object... Method. Invoke (circle,15,"Circle"); Method 1 = clazz.getDeclaredMethod(clazz.getDeclaredMethod)"drawCircle"); // Modify the access identifier for private methods method1.setaccessible (true); method1.invoke(circle); Method 2 =clazz.getDeclaredMethod()"getAllCount");
Integer count = (Integer) method2.invoke(circle);
System.out.println("count:"+count); DrawCircle count:100 */ drawCircle count:100 */Copy the code

Invoke a Method from the above code using the invoke(Object obj,Object… The first argument represents the object to call, and the second argument is passed as the argument to call the method. This completes the dynamic invocation of the class method.

Method return value Method names Method statement
Object invoke(Object obj, Object… args) Calls the underlying Method represented by this Method object on the specified object with the specified parameters.
Class<? > getReturnType() Returns a Class object that describes the formal return type of the Method represented by this Method object, that is, the return type of the Method
Type getGenericReturnType() Returns a Type object that represents the formal return Type of the Method represented by this Method object and is also the return Type of the Method.
Class<? > [] getParameterTypes() Returns, in declarative order, an array of Class objects that describe the parameter types of the methods represented by this Method object. Returns an array of method parameter types
Type[] getGenericParameterTypes() Returns, in declarative order, an array of Type objects that describe the parameter types of the Method represented by the Method object, as well as the parameter types of the returned Method
String getName() Returns the name of the Method represented by this Method object as a String, that is, the name of the returned Method
boolean isVarArgs() Returns true if the method is declared to take a variable number of arguments. Otherwise, return false.
String toGenericString() Returns a string describing this Method, including type parameters.

GetReturnType /getGenericReturnType both get the return Type of the Method represented by the Method object, except that the getReturnType returns the Class Type and the getGenericReturnType returns the Type(as previously analyzed), which is an interface. A new default method implementation in Java8 that returns information about the parameter type

Public interface Type {//1.8 Added default StringgetTypeName() {
        returntoString(); }}Copy the code

And the same is true with getParameterTypes/getGenericParameterTypes, retrieved Method objects are represented by the Method of parameter types, in front of the other methods and the Field and the Constructor is similar.