First, Java reflection mechanism overview

The Java radiation mechanism means that for any class in the == health state ==, all the properties and methods of that class can be known. You can call any method or property of any object; This ability to dynamically retrieve information and dynamically invoke methods becomes Java’s reflection mechanism.

Second, the role of reflection

  1. Using the Java mechanism, some protected or even private methods or classes can be dynamically called in Java programs, which can largely meet some special needs.
  2. In the Source code of the Android SDK, many classes or methods are often annotated with the “@hide” comment tag, which makes the method or class invisible when the SDK is generated, so the program may not compile and may have problems when it is finally released. The first way to solve this problem is to remove the “@hide” tag from the source code yourself, and then recompile to generate an SDK. Another approach is to use The Java reflection mechanism, which allows you to access methods that have access rights or modify their access domains.
  3. Some people may wonder, why do I use reflection when I could just use a new object? Doesn’t the amount of code increase instead? The point of reflection is not to make it easy for you to create an object, but to make your code more flexible, less coupled, and more adaptive.

How to reduce the coupling degree, improve the code adaptive ability?

Through the interface, but if the interface needs to use the new keyword, then the coupling problem will arise again

Here’s an example:

/** /** * @classname: TestReflection * @model: (module name) * @description: Public class TestReflection {/** /** * main * @author Administrator * @date 2017年 06 月2日 5:09:38 */ public class TestReflection {/** /** * main * @param args * void * @modifiedPerson Administrator * @date 2017年6月2日 5:09:38 PM */ public static void Main (String[] args) {// use New ITest ITest = createITest("ITestImpl1");
        iTest.testReflect();
        ITest iTest2 = createITest("ITestImpl2"); iTest2.testReflect(); } /** * createITest (); /** * createITest ()ifStatement to return different ITest objects? * @param name * @return* ITest * @modifiedPerson Administrator * @date 2017年6月2日 5:32:21 */ public static ITest createITest(String name){if (name.equals("ITestImpl1")) {
            return new ITestImpl1();
        } else if(name.equals("ITestImpl2")) {return new ITestImpl2();
        }
    
        return null;
    }

}


interface ITest{
    public void testReflect();
}

class ITestImpl1 implements ITest{

    /* (non-Javadoc)
    * <p>Title: test</p> 
    * <p>Description: </p>  
    * @see ITest#test()
    */
    @Override
    public void testReflect() {

         System.out.println("I am ITestImpl1 !");
    }
}

class ITestImpl2 implements ITest{

    /* (non-Javadoc)
    * <p>Title: testReflect</p> 
    * <p>Description: </p>  
    * @see ITest#testReflect()
    */
    @Override
    public void testReflect() {

        System.out.println("I am ITestImpl2 !"); }}Copy the code

If you have 1000 different ITests to create, are you going to write 1000 if statements to return different ITests?

What about using reflection?

/** /** * @classname: TestReflection * @model: (module name) * @description: Public class TestReflection {/** /** * main * @author Administrator * @date 2017年 06 月2日 5:09:38 */ public class TestReflection {/** /** * main * @param args * void * @modifiedPerson Administrator * @date 2017年6月2日 5:09:38 PM */ public static void Main (String[] args) {// use New ITest ITest = createITest("ITestImpl1");
        iTest.testReflect();
        ITest iTest2 = createITest("ITestImpl2"); iTest2.testReflect(); ITest iTest3 = createITest2(ITest iTest3 = createITest2)"ITestImpl1");
        iTest3.testReflect();
        ITest iTest4 = createITest2("ITestImpl2"); iTest4.testReflect(); } /** * createITest (); /** * createITest ()ifStatement to return different ITest objects? * @param name * @return* ITest * @modifiedPerson Administrator * @date 2017年6月2日 5:32:21 */ public static ITest createITest(String name){if (name.equals("ITestImpl1")) {
            return new ITestImpl1();
        } else if(name.equals("ITestImpl2")) {return new ITestImpl2();
        }
    
        returnnull; } /** * createITest2 uses reflection: when 1000 different ITests need to be created, you don't have to create an ITest object for each onereturn* ITest * @modifiedPerson Administrator * @date 2017年6月2 PM 5:34:55 */ public static ITest createITest2(String name){ try { Class<? > class1 = Class.forName(name); ITest iTest = (ITest) class1.newInstance();return iTest;
        } catch (ClassNotFoundException e) {

            e.printStackTrace();
        } catch (InstantiationException e) {

            e.printStackTrace();
        } catch (IllegalAccessException e) {

            e.printStackTrace();
        }
        
        return null;
        
    }

}


interface ITest{
    public void testReflect();
}

class ITestImpl1 implements ITest{

    /* (non-Javadoc)
    * <p>Title: test</p> 
    * <p>Description: </p>  
    * @see ITest#test()
    */
    @Override
    public void testReflect() {

         System.out.println("I am ITestImpl1 !");
    }
}

class ITestImpl2 implements ITest{

    /* (non-Javadoc)
    * <p>Title: testReflect</p> 
    * <p>Description: </p>  
    * @see ITest#testReflect()
    */
    @Override
    public void testReflect() {

        System.out.println("I am ITestImpl2 !"); }}Copy the code

The principle of decoupling using reflection is to create objects “dynamically” using reflection: pass in the package name of the Hero class to createITest(). Class name by loading the specified class and then instantiating the object.

Understand Class classes and Class types

To understand reflection, you must first understand the Class Class, because the Class Class is the basis of the reflection implementation.

3.1 Is a class an object

In the object-oriented world, everything is an object. An object is an instance of a Class, so a Class is an instance object of a Java.lang. Class Class, and Class is the Class of all classes.

3.2 Obtaining an object of Class

For normal objects, we create an object directly with new.

Student sdutent = new Student ();

But the object of a Class is a Class and cannot be created with new. The source code for Class is described as follows:

/*
     * 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 field forclassLoader. The initialization value of non-null // prevents future JIT optimizations from assuming this final field is  null. classLoader = loader; }Copy the code

The constructor is private. Only the Java Virtual Machine (JVM) can create an object of a Class. It cannot create a new Class object like a normal Class. A Class object can only be obtained from an existing Class (three methods) :

The first method
Class<? > cls = Class.forName("com.example.student"); //forName (Package Name. Class name) Student s1 = (Student)cls.newInstance();Copy the code
  1. Finds and loads the specified class through the JVM
  2. Call newInstance() to create an instance of the loaded class in memory and assign the instance to S1
The second way
Student s = new Student; Class<? > cls = s.getClass; Student s2 = (Student)cls.newInstance();Copy the code
  1. Create a new instance of Student in memory. Object S refers to this memory address
  2. Object s calls the getClass() method to return the Class object to which object s corresponds
  3. Calling newInstance() causes the Class object to create an instance of the object in memory and s2 to refer to the memory address of the instance
The third way
Class<? > cls = Student.Class(); Student s3 = (Student)cls.newInstance();Copy the code
  1. Gets a Class object of the specified type, in this case Student
  2. The newInstance() method is called to create an instance of the Class object in memory, and S3 refers to the memory address of the instance
Note:
  • The cls.newinstance () method returns a generic T, which we must convert to the Student class
  • Cls.newinstance () returns the no-argument constructed object of the Student class by default
  • Classes loaded by reflection must have no parameter constructors. If not, an exception will be thrown

The difference between creating a class with a class type and creating a class with new is that the class type creates a dynamically loaded class.

4. Dynamically load classes

Program execution is divided into compiler and runtime. When a class is loaded at compile time, it is called a static class. When a class is loaded at runtime, it is called a dynamic class.

Let’s get rid of the IDE and use Notepad to write classes. This is so that we can manually compile and run a class using the CMD command line to better understand the difference between dynamically loaded and statically loaded classes.

First write First. Java

class First
{
    public static void main(String[] args)
    {
        if ("Word".equals(args[0])) {// load the class statically and load Word w = new Word(); w.start(); }if ("Excel".equals(args[0])) { Excel e = new Excel(); e.start(); }}}Copy the code

Then go to CMD and compile first.java

Because our two new classes, Word and Excel, did not compile, so we reported an error. This is the disadvantage of static loading classes, that is, all possible classes must be loaded at compile time, but we want to implement the implementation of the run time to load the class which is used, the next step is to dynamically load the class to improve.

Improved class: firstbetter.java

Class FirstBetter {public static void main(String[] args) {try {c = class.forname (args[0]); // Create an object of the class type. FirstAble OA = (FirstAble) c.newinstance (); oa.start(); } catch (Exception e) { e.printStackTrace(); }}}Copy the code

Args [0] is the first argument to the main method at runtime. If you type Word, it will load Word. Java. In this case, create word. Java in the same path as firstbetter.java. Similarly, if you type Excel you need to load Excel. Among them, FirstAble is an interface. The above dynamically loaded classes, such as Word and Excel, implement FirstAble, reflecting the idea of polymorphism. Such dynamic loading and polymorphism can decouple specific functions and code. I want PPT) can dynamically add, without changing the original code.

The FirstAble interfaces are as follows:

interface FirstAble
{
    public void start();
}
Copy the code

Word categories:

class Word implements FirstAble
{
    public void start()
    {
        System.out.println("word... starts..."); }}Copy the code

Compile and run the above classes in sequence.

Get information about the class

A class usually contains properties and methods. Reflection is used to get the class constructors, member methods, member variables, modifiers (of methods and variables), and so on.

5.1 Getting the constructor of the class

What does a constructor contain: constructor arguments

Into the Constructor of a class is an object, it is a Java. Lang. Reflect. The Constructor of an object, so we through the Java. Lang. Reflect. Encapsulated inside the Constructor method to get the information.

1. Get a constructor separately

This is done by the Class Class:

  • public Constructor getDeclaredConstructor(Class
    … ParameterTypes) // Return a specific constructor based on the constructor parameters (both public and non-public)
  • public Constructor getConstructor(Class
    … ParameterTypes) // Returns a concrete constructor with public properties based on the constructor’s parameters
  • The parameterTypes parameter is a list of class types for the constructor parameter class.

For example, class A has the following constructor:

public A(String a, int b) {
    // code body
}
Copy the code

Then it can be done by:

Constructor constructor = a.getDeclaredConstructor(String.class, int.class);
Copy the code

To get the constructor.

Get all constructors

This is done by the Class Class:

  • Constructor getDeclaredConstructors() returns an array of constructors for this class (public and nonpublic).
  • Constructor getConstructors() returns an array of all constructors with public properties

This can be done through the following steps:

1, given an object, get the class type of its class

Class c = obj.getClass();
Copy the code

Get all constructors for this class and put them in an array

Constructor[] constructors = c.getDeclaredConstructors();
Copy the code

3. Iterate over an array of constructors to obtain a constructor

for (Constructor constructor : constructors)
Copy the code

Get an array of class types for the constructor parameter types

Class[] paramTypes = constructor.getParameterTypes();
Copy the code

Class type (class type) = class type (class type) = class type (class type

for (Class class1 : paramTypes)
Copy the code

6. Obtain the type name of the parameter

String paramName = class1.getName();
Copy the code

Example:

private static void forName2GetConstructor() {try {// first method:forName() Class<? > class1 = Class.forName("com.zyt.reflect.StudentInfo"); Constructor<? >[] constructors = class1.getDeclaredConstructors();for(Constructor<? > constructor : constructors) { System.out.print("Construction method:"+constructor.getName()+"Parameter type:"); Class<? >[] parameterTypes = constructor.getParameterTypes();for(Class<? > class2 : parameterTypes) { System.out.print(class2.getName()+",");
                }
                System.out.print("\n");
            }
            
            //调用构造方法
            Constructor<?> constructor = class1.getDeclaredConstructor(String.class, String.class, int.class);
            StudentInfo instance = (StudentInfo) constructor.newInstance("Zhang"."Male", 18);
            System.out.println("Call constructor =="+instance.getName()+","+instance.getScore()); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); }}Copy the code

5.2 Obtaining member methods of a class

What does a member method contain: return value type + method name + parameter type

In Java, the member Method of a class is also an object. It is an object of java.lang.reflect.Method, so we get this information from the Method encapsulated in java.lang.reflect.Method.

1. Get a method separately
  • Method getMethod(String name, Class[] params) returns a specific Method with public properties based on the Method name and parameters
  • Method getDeclaredMethod(String name, Class[] params)
  • The two arguments are the method name and the class type list of the method parameter class.

For example, class A has the following method:

public void print(String a, int b) {
    // code body
}
Copy the code

Now that we know that A has an object A, we can pass:

Class c = a.getClass();
Method method = c.getDeclaredMethod("print", String.class, int.class);
Copy the code

To get this method.

How do I call the obtained method

How do we call this Method once we have the Method? We do this by using the following Method of the Method class:

Public Object Invoke (Object obj, Object... args)Copy the code

The two arguments are the object to which the method belongs and the arguments required by the method.

method.invoke(a, "hello", 10);
Copy the code

And by ordinary call:

a.print("hello", 10);
Copy the code

The effect is exactly the same. This is the reflection of the method. The invoke() method can in turn call the method with its object as a parameter, exactly the opposite of normal.

Retrieve information about all member methods in a class
  • Method[] getMethods() returns an array of all methods with public properties
  • Method[] getDeclaredMethods() returns an array of methods in the class (both public and nonpublic)
Note:

GetMethods () : getMethods() : getMethods() : getMethods() : getMethods() : getMethods() : getMethods(); getMethods() : getMethods(); getMethods() : getMethods();

GetDeclaredMethods () : getDeclaredMethods() : Gets all member methods and implemented interface methods defined in the current class, excluding methods inherited from the superclass.

Check out the development documentation for an explanation:

getMethods() - Returns an array containing Method objects for all public methods forthe class C represented by this Class. &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; Methods may be declaredin C, the interfaces it implements or inthe superclasses of C. &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; The elementsin the returned array are in no particular order. 

getDeclaredMethods() - Returns a Method object whichrepresents the method matching the specified name and parameter types &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; that is declared by the class represented by this Class.Copy the code

So in the sample code the method get_Reflection_Method(…) The ReflectionTest class inherits from the Object class, implements the actionPerformed method, and defines the following member methods:

A, Method[] methods = temp.getdeclaredmethods ()

   

B, Method[] methods = temp.getmethods ()

  

Method:

public invoke( obj,                       ... args)
Copy the code

Calls the underlying Method represented by this Method object on the specified object with the specified arguments. Individual parameters are automatically unpacked to match the base parameters, and both the base and reference parameters are subject to method call conversions as needed.

  • If the underlying method is static, the specified OBj parameter can be ignored. This parameter can be null.

  • If the form parameter required by the underlying method is 0, the supplied args array can be 0 or null in length.

  • If the underlying method is an instance method, it is invoked using dynamic method lookup, as documented in Section 15.12.4.4 of the Java Language Specification, Second Edition; This is especially true when overrides occur based on the runtime type of the target object.

  • If the underlying method is static and the class that declared the method has not yet been initialized, it is initialized.

  • If the method completes normally, the value returned by the method is returned to the caller; If the value is of a primitive type, it is first appropriately wrapped in an object. However, if the value’s type is a set of basic types, the array elements are not wrapped in an object; In other words, an array of primitive types is returned. This call returns null if the underlying method returns type void.

Parameters:

Obj – The object from which the underlying method is called

Args – Parameters used for method calls

Returns:

If you want to get information about all of the member methods in a class, rather than about a single member method, you can do so by following these steps:

1, given an object, get the class type of its class

Class c = obj.getClass();
Copy the code

2. Get all the methods of the class and put them in an array

Method[] methods = c.getDeclaredMethods();
Copy the code

3. Iterate over an array of methods to obtain a method

for (Method method : methods)
Copy the code

Get the class type of the method return value type

Class returnType = method.getReturnType();
Copy the code

Get the name of the type of the method return value

String returnTypeName = returnType.getName();
Copy the code

Get the name of the method

String methodName = method.getName();
Copy the code

Get an array of class types for all parameter types

Class[] paramTypes = method.getParameterTypes();
Copy the code

Class class type (class type) = class type (class type

for (Class class1 : paramTypes)
Copy the code

9, get the type name of the parameter

String paramName = class1.getName();
Copy the code

Example:

private static void getClass2GetMethod(){
        StudentInfo studentInfo = new StudentInfo();
        Class<? extends StudentInfo> class1 = studentInfo.getClass();
        
        Method[] methods = class1.getDeclaredMethods();
        for (Method method : methods) {
            System.out.print("Method name:"+method.getName()); Class<? >[] parameterTypes = method.getParameterTypes();for(Class<? > class2 : parameterTypes) { System.out.print("Parameter type:"+class2.getName()); } Class<? >returnType = method.getReturnType();
            System.out.println(Return value type:+returnType.getName()); Method1 = class1. GetDeclaredMethod ();"setName", String.class);
            Method method2 = class1.getDeclaredMethod("getName");
            method1.invoke(studentInfo, "Bill");
            String name = (String) method2.invoke(studentInfo);
            System.out.println("Call the non-static method getName()==name:"+name); //2, set the first argument of invoke to null system.out.println ();"Call static method test() :");
            Method method3 = class1.getDeclaredMethod("test");
            method3.invoke(null);
            Method method4 = class1.getDeclaredMethod("test", String.class);
            method4.invoke(null, "123456"); //3, call private method: before the method call, need to put the methodsetAccessible
            Method method5 = class1.getDeclaredMethod("getAge");
            method5.setAccessible(true);
            System.out.println("Call the private method getAge()=="+method5.invoke(studentInfo)); Class1. GetDeclaredMethod () = getDeclaredMethod();"showMsg", String.class,int.class,MsgClass.class);
            //Method method6 = class1.getDeclaredMethod("showMsg", new Class[]{String.class,int.class,MsgClass.class});
            //method6.invoke(studentInfo, new Object[]{"Wang Xiao Wu",28,new MsgClass()});
            method6.invoke(studentInfo,"Zhao Xiaoliu",28,new MsgClass()); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); }}Copy the code

5.3 Getting member variables of a class

What does a member variable contain: member variable type + member variable name

The member variable of the class is also an object, which is an object of the Java.lang.reflect. Field, so we get this information through methods wrapped in java.lang.reflect.Field.

1. Obtain a member variable separately
  • Field getField(String name) Returns a specific member variable with a public property based on the variable name
  • Field getDeclaredField(String name) Returns a member variable based on the variable name (both public and non-public).
  • Arguments are the names of member variables.

For example, A class A has the following member variables:

private int n;
Copy the code

If A has an object A, then its member variables can be obtained as follows:

Class c = a.getClass();
Field field = c.getDeclaredField("n");
Copy the code
Get all member variables
  • Field[] getFields() returns an array of member variables with public properties
  • Field[] getDelcaredField() returns an array of all member variables (public and nonpublic)

Similarly, if you want to obtain information about all member variables, you can do the following:

1, given an object, get the class type of its class

Class c = obj.getClass();
Copy the code

Get all member variables of the class and put them in an array

Field[] fields = c.getDeclaredFields();
Copy the code

3, iterate through the array of variables, get a member variable field

for (Field field : fields)
Copy the code

Get the class type of the member variable type

Class fieldType = field.getType();
Copy the code

Get the type name of the member variable

String typeName = fieldType.getName();
Copy the code

6, get the name of the member variable

String fieldName = field.getName();
Copy the code

Example:

private static void class2GetField() { Class<? > class1 = StudentInfo.class; Field[] fields = class1.getDeclaredFields();for (Field field : fields) {
            System.out.print("Variable name:"+field.getName()); Class<? >type = field.getType();
            System.out.println("Type:"+type.getName()); } try {// Access the non-private variable StudentInfo StudentInfo = new StudentInfo(); Field field = class1.getDeclaredField("name");
            System.out.println("Variable name=="+field.get(studentInfo));
            Field field2 = class1.getDeclaredField("school");
            System.out.println("Static variable school=="+field2.get(studentInfo)); Field3 = class1. GetDeclaredField ();"age");
            field3.setAccessible(true);
            System.out.println("Private variable age=="+field3.get(studentInfo));
            field3.set(studentInfo, 18);
            System.out.println("Private variable age=="+field3.get(studentInfo)); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); }}Copy the code

5.4 Get the decorating fields of classes, methods, and attributes

Classes Class, Method, Constructor, and Field all have a public Method, int getModifiers(). This Method returns a number of type int representing the combined value of the decorated types of the decorated object (Class, Method, Constructor, Field).

In the development documentation, you can see that the Modifier class defines a number of specific Modifier fields, each of which is a fixed int value, as listed below:

Not only does this class provide several methods to determine if you have a modified field: Boolean isXXXXX(int Modifiers), but also a String toString(int modifier) method. Converts an int representing the combined value of a decorated field to a string describing the decorated field.

5.5 Obtaining private member variables and private methods through reflection

The Person class

public class Person {
private String name = "zhangsan";
private String age;
 
public String getName() {
    return name;
}
 
public void setName(String name) { this.name = name; } // Main function Person Person = new Person(); System.out.println(); // Println ();"before:" + getPrivateValue(person, "name"));
    person.setName("lisi"); System.out.println();"after:" + getPrivateValue(person, "name")); /** * Get private member variable ** @param person * @ by reflectionreturn*/ private Object getPrivateValue(Person person, String fieldName) { try { Field field = person.getClass().getDeclaredField(fieldName); // The parameter value istrueEnable disable access control check //setAccessible(trueInstead of changing the method's access to public, Java's permission control checks are removed. // So even if it is a public method, the object identifier of this object is defaultfalse
        field.setAccessible(true);
        return field.get(person);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}  
Copy the code

Running result:

Access to private methods similar Filed class access to private member variables, Method detailed view developer documentation, such as: developer.android.com/intl/zh-cn/…

Some advanced topics about reflection

If those are the basics of Java reflection, we’ll end the article with some more advanced topics of reflection. In addition, this article to the basic knowledge of the explanation only belongs to the backbone, some specific side can see their own documentation. It should be noted that arrays are optimized separately in Java reflection, as shown in the java.lang.reflect.Array class. And about the support of the generic type, but check the Java. Lang. Reflect. ParameterizedType and related information.

There are three advanced topics temporarily thought of, because the Understanding of Java reflection is not deep, so only from the train of thought to discuss, specific implementation, you can refer to other relevant materials, do more in-depth research.

Android compile time issue

The security permissions on Android I’ve broken down into three simple layers, the least stringent of which is the “@hide” flag that just fooled the compiler. For an open source operating system, the tag itself has no security limitations. However, from what the Engineer in charge of Android from Google said last time, the role of this tag is more convenient for hardware manufacturers to do closed-source secondary development. That’s a reasonable explanation.

That doesn’t stop us from using reflection to get around the first layer of native Android security. If you’re familiar with the source code, you’ll see that this can be applied to a lot of places. And crucially, you don’t need to compile it in source code, just like a normal application development process.

I can’t list the specific scope of use, such as custom Windows, installation programs, and so on. Simply put, using reflection on Android gives you a deeper understanding and greater control over the Android system.

Decoupling of software

We often talk about decoupling, weak coupling, when architecting code. In fact, decoupling and is not just about code. We can consider situations where the functional requirements of the software cannot be fully determined at the outset, and some features are added or removed late in the development process, even after the software has been released. According to our usual thinking, this situation will have to change the source code, recompile. If the software has been released, then the customer has to reinstall the software. On reflection, do we think that software and programs are the same thing? In fact, if you can understand the software and the program separately, then you will find that there are other solutions to deal with the above situation.

Our country has a very important but very troublesome system, that is the household registration system. It was meant to better manage population matters. Every time a child is born, we need to apply for household registration in the place where household registration is managed. And when a person dies, we also need to sell his or her household registration in the appropriate place. Since we can regard classes as life, can we dynamically manage classes by learning such a household registration management system?

In fact, such management is possible, and the Java Virtual Machine itself is based on such mechanisms to run programs. So whether we can architecture a software framework this way. First of all, our software has a configuration file, which is actually a piece of text that describes in detail, once the core of our software is running, what paths to load, what classes to call, and what methods to call. So when we need to add or subtract functionality, we can simply modify the configuration text file and then delete or add the corresponding.class file.

If you are sensitive enough, you may find that the configuration file formed this way is almost equivalent to a scripting language. We also wrote the interpreter for this script, and the key is that it is developed, so you can add new classes to it dynamically to increase its functionality.

Don’t assume that this is just an idea, although developing a full-fledged scripting language can be tricky. However, in some large projects on the network side, the combination of configuration files + ClassLoader + reflection mechanism to form software decoupling has been used more commonly. So I’m not proposing an idea here, but I’m introducing an industry solution for dealing with this kind of problem.

Reflective safety

At this point in the article, I think you can honestly say how powerful the Java reflection mechanism is. However, if you are a bit security-conscious, the Java mechanism may seem a little too powerful. As mentioned earlier, Java reflection can even access private methods and properties. In order to give you a more comprehensive understanding of Java reflection and establish a correct outlook on life and values, this section will give you an overview of Java security issues.

Java is a safer language than C++. This is closely related to how they work. C++ runs locally, which means that almost all programs have the same permissions in theory. Java, on the other hand, is a “sandbox” environment because it runs in a virtual machine and is not directly connected to the outside world. Java’s security mechanisms are complex, at least to me. As a security model for Java, it includes a series of components: bytecode validators, class loaders, security managers, access controllers, and so on. As mentioned earlier, I’ve divided Android security permissions into three levels: the first level is for the “@hide” tag at compile time; The second level is for access permissions such as private; The third level is a Permission mechanism managed by the security manager.

Java reflection does have access to private methods and properties, which is one way to bypass the second level of security. Is it something like a “back door” left behind by Java itself for some purpose, or is it for debugging purposes? In any case, the idea is to turn off access security checks.

If you’re in the spirit of independent exploration, you’ll notice that the Field, Method, and Constructor classes we mentioned earlier all have a common parent class AccessibleObject. AccessibleObject has a public method: void setAccessible(Boolean flag). It is this method that allows us to dynamically turn access security checks on or off to access methods or fields that would otherwise be private. In addition, the access security check is a time-consuming operation, and turning it off will improve performance.

Don’t think we’re complacent about bypassing the first two levels of security, because they’re not really set up for security. Their role is more to improve the rules. The third level of security is really designed to prevent malicious attacks. With this level of protection, you may not even get the ReflectPermission, and nothing else.

Understand the nature of set generics through reflection

First, conclusion:

Generics of collections in Java, which are designed to prevent input errors, are valid only at compile time, not at run time. Here is an example to verify:

package com.Soul.reflect; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; /** * Public class Generic {public static void * @description * @author Soul * @date */ public class Generic {public static void main(String[] args) { List list1 = new ArrayList(); List2 = new ArrayList<String>(); // list2. Add (list2); // list2. Add (list2);"hello"); // list2.add(20); / / an error! System.out.println(int);The length of list2 is:+ list2.size()); // If list2 is 1 in length /* * * 2. If list2 is 1 in length /* * 2, list1 is 1 in length /* * 2. If list1 is 1 in length, list2 is 1 in length /* * 2. C1 = list1.getClass(); c1 = list1.getClass(); Class c2 = list2.getClass(); System.out.println(c1 == c2); / / the result:trueTry {Method m = c2.getMethod(Method m = c2.getMethod(Method m = c2.getMethod(Method m = c2.getMethod));"add", Object.class); // Add method minnvoke (list2, 20); // Add an int to list2, which displays an error in the compiler: system.out.println (The length of list2 is:+ list2.size()); } catch (Exception e) {e.printStackTrace();} catch (Exception e) {e.printStackTrace(); } /* * The compiler uses generics to restrict the types of elements in the set to be the same, but after the compiler ends and enters the * runtime, the generics are no longer useful, even if elements of different types can be inserted into the set. * /}}Copy the code

The output

The length of list2 is 1. True The length of list2 is 2


    As long as you learn something you couldn’t before, and as long as the person you are today is better than the person you were yesterday, you’re on the way to advancement.