Review java reflection to give you a new understanding of reflection

During normal class operations, you must first determine the class to use, and then use the keyword new to generate instantiated objects. However, in reflection, it can be implemented through the getClass() = (public final class <? > getClass()) = = method in the Object class

1.Class object instantiation

The first method: call the getClass() method in the Object class. To use this class, you must have an instantiated Object

mport java.util.Date;
public class Person {
    public static void main(String[] args) {
        Date date = new Date();
        Class<?> clazz = date.getClass();
        System.out.println(date.getClass());
        System.out.println(clazz.getName());
    }
}
Operation results:
class java.util.Date
java.util.Date

The second method: use "class. Class" to obtain. At this time, it is not allowed to obtain through the specified instantiated object.

public class Person {
    public static void main(String[] args) {

        Class<?> clazz = java.util.Date.class;
        System.out.println(clazz.getName());

    }
}
Operation results:
java.util.Date

The third method: call the methods provided by Class: public static Class <? > forName(String className)Throws ClassNotFoundException

public class Person {
    public static void main(String[] args) throws Exception {
	//This method only needs to define a specific name to get the reflection operation class object. If this class does exist, an exception will be thrown
        Class<?> clazz = Class.forName("java.util.Date");
        System.out.println(clazz.getName());
    }
}
  • Using the getClass() method operation, there are generally simple automatic assignment operations of Java classes and submission parameters. For example, Struts and Spring MVC will provide automatic conversion of form parameters and simple java classes.

  • The method of using class. Class is often to set the type of reflection operation for users, such as data saving in Hibernate and querying according to ID;

  • The Class.forName() method can be used to realize the reflection operation of configuration file and Annotation configuration. Almost all development frameworks rely on this method.

2. Reflect instanced objects

Next, you can use the Class class to control the reflection of the Class. There are some commonly used methods in Class, which can be viewed on Baidu (10 commonly used)
It should be noted that if the Class object is instantiated by using the newInstance() method in the Class class, the Class must provide a parameterless construction method, otherwise syntax errors will occur. You can also go further and use reflection to call the specified parameterless construct.

package com.cj;

/*
* Instantiate objects with reflections
* */

//Create a Book class
class Book{
//    Nonparametric construction method of Book
    public Book(){
        System.out.println("Book Nonparametric construction method of class");
    }

//  @Override indicates that the marked method overloads the method of the parent class and plays the role of assertion. There is no overloaded parent class here
    @Override
    public String toString() {
        return "java Developing reflective instantiation object learning";
    }
}

public class Person {
    public static void main(String[] args) throws Exception {
        Class<?> clazz = Class.forName("com.cj.Book");   //Sets the name of the operand class
//        All objects after reflection instantiation are of Object type
        Object obj = clazz.newInstance();   //It is equivalent to using new to call the parameterless construction method
        Book book = (Book) obj ;
        System.out.println(book);
    }
}
Operation results:
Book Nonparametric construction method of class
java Developing reflective instantiation object learning

Instead of instantiating Book through the keyword new, the code instantiates the Object through the operation Class name defined by the Class class and the newInstance() method. At this time, the parameterless construction in the Class will be called by default. However, the Object type returned by this method needs to be transformed downward into a subclass instance.

What's the point of java doing this?

A: instantiating objects using reflection mechanism can achieve better decoupling operation.

Using reflection to realize factory design pattern

package com.cj;

/*
* Instantiate objects with reflections
* */

interface Fruit{
    // action
    public void eat();
}
class Apple implements Fruit{
    @Override
    public void eat(){
        System.out.println("eat Apple");
    }
}
class Orange implements Fruit{
    @Override
    public void eat(){
        System.out.println("eat a mandarin orange");
    }
}
class Factory {
    public static Fruit getInstance(String className) {
        Fruit fruit = null;
        try {   //Reflection instantiation, subclass objects can be received using Fruit
            fruit = (Fruit) Class.forName(className).newInstance();
        } catch (Exception e) {
            //Exception not handled
        }
        return fruit;
    }
}

public class Person {
    public static void main(String[] args) {
        //Pass class name directly
        Fruit fa = Factory.getInstance("com.cj.Apple");
        Fruit fb = Factory.getInstance("com.cj.Orange");
        fa.eat();
        fb.eat();
    }
}
Operation results:
eat Apple
eat a mandarin orange

In the actual development, combining the above factory design patterns with some configuration files, such as XML format files, you can use the configuration files to dynamically define the operation classes required in the project. At this time, the program will become very flexible.

3. Use reflection call construction

The limitation of using newInstance() method to implement reflection instantiation object is that it needs to provide parameterless construction. Therefore, when there are only parameter constructs in the class, the reflection instantiation operation of the object must be realized through the java.lang.reflect.Constructor class.

Although there are solutions, the number of parameters in the construction method of each class may be different. At this time, it will be troublesome to write a public tool class that reflects the instantiated object.

Gets the constructor in the class
Get all construction methods: public constructor <? > [] getConstructors() throws SecurityException
Gets the constructor of the specified parameter type: public constructor < T > getconstructor (class <? >... Parametertypes) throws nosuchmethodexception, SecurityException

Common operation methods of Constructor class
return: method name
Return all types that throw exceptions on the constructor (class <? > []): getExceptionTypes()
Get modifier (int) of constructor: getModifiers()
Get the name of the constructor (String): getName()
Get the number of parameters in the constructor (int): getParameterCount()
Get the parameter type class <? > in the constructor []): getParameterTypes()
Call the constructor of the specified parameter to instantiate the class object (T): newinstance (object... Initargs) this method uses variable parameterization

Modifiers are described by numbers. All modifiers are essentially digital addition operations. If (public=1, final=16), then (public final) = (1 + 16) 17, the constant operation corresponding to each modifier is clearly defined in the java.lang.reflect.modifier class.
Method of number to modifier: public static String toString (int mod)

package com.cj;


import java.lang.reflect.Constructor;

class Book{
    private String title;
    private double price;
    public Book(String title,double price){
        this.title = title;
        this.price = price ;
    }
    public String toString(){
        return "Book name:" + this.title +","+"Book price:"+this.price ;
    }
}


public class Person {
    public static void main(String[] args) throws Exception{    //This class needs to exist, so you need to throw an exception
        Class<?> clazz = Class.forName("com.cj.Book");
//        Explicitly find the construction of two parameters in the Book class. The first is String and the second is double
        Constructor<?> constructor = clazz.getConstructor(String.class ,double.class);
        Object object = constructor.newInstance("java actual combat",11.2);
        System.out.println(object);
    }
}
Operation results:
Book name:java actual combat,Book price:11.2
4. Reflection calling method

The operation of Class methods is realized by reflection mechanism, which can be completed by Class class
Class gets the operation of a common method
Get all methods (Method []): getMethods()
Gets the Method (Method) of the specified Method name and parameter type in the specified class: getmethod (string name, class <? >... Parametertypes)

Common methods of Method class
Get method modifier (int): getModifiers()
getReturnType()
getParameterCount()
getParameterTypes()
Reflection calls the method and passes the parameter data required to execute the method: invoke (object, object... Args)
getExceptionTypes()

invoke() reflects the core operation of the call.

package com.cj;


import java.lang.reflect.Method;
import java.util.*;
class Book{
    private String title;

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }
}


public class Person {
//    First way to capitalize
    public static String initcap(String string){
        char[] chars = string.toCharArray();
        if(chars[0]>='a' && chars[0]<='z'){
            chars[0] = (char) (chars[0]-32);
        }
        return new String(chars);
    }
//    The second method
    public static String initcaps(String string){
    //Substring substring
        return string.substring(0,1).toUpperCase() +string.substring(1);
    }
    public static void main(String[] args)throws Exception {
        String fieldName = "title";  //The name of the member to operate on
        Class<?> clazz = Class.forName("com.cj.Book");  //Gets the reflection object to operate on
        Object object = clazz.newInstance();    //Instantiate object
//        Get the setTitle method in the class. Since the first letter of the title needs to be capitalized, call init for processing. The parameter type is String
        Method setMed = clazz.getMethod("set" + initcap(fieldName),String.class);
//        Get the getTitle method in the class. This method does not accept parameters and has no return value type declaration
        Method getMed = clazz.getMethod("get"+initcap(fieldName));
        setMed.invoke(object,"java development");
        System.out.println("title:"+getMed.invoke(object));

    }
}

Operation results:
title: java development

After obtaining the Method object of the corresponding Method, you can use invoke() to specify the instantiated object of the class where the Method is located and the corresponding parameters to realize the reflection call of the Method.

5. Reflection calling member

Members still need to be obtained through Class methods.

Operation to get a member from Class
Get all members of this class definition (Field []): getdeclaraedfields()
Get the member (Field) with the specified name of this class: getDeclaredField(String name)
Get all members of the inherited parent class of this class (Field []): getFields()
Get the member (Field) with the specified name in the parent class inherited by this class: getField(String name)

The return value types are java.lang.reflect.Field, which can describe the information of class members. Some methods are also defined in the Field class.

Common methods of Field class
getType()
get(Object obj)
set(Object obj,Object value)
There are also many setXxx(), getXxx(), and you can view the official documents by yourself.

package com.cj;


import java.lang.reflect.Field;

class Book{
    private String title;
    //Private property does not define setter and getter methods
}


public class Person {

    public static void main(String[] args)throws Exception {
        Class<?> clazz = Class.forName("com.cj.Book");  //Get reflection object
        Object object = clazz.newInstance();    //Give instantiated object
        Field titleField = clazz.getDeclaredField("title"); //Get the title attribute in the class;
        titleField.setAccessible(true); //Unpack
        titleField.set(object,"java development");	//Equivalent to: this.title = "java development"
        System.out.println(titleField.get(object));	//Equivalent to: this.title
    }
}
Operation results:
java development

Note that when the encapsulation operation is cancelled, an error will be reported if setAccessible(true) is not used. Although this can directly access members, such code is not standard in a strict sense. All properties are accessed through setter and getter methods.

How to determine the language environment of the current software project; To realize multi language switching, a resource file must be provided for each language, and different resource files can be selected for information reading according to the language environment.

6. Use the Locale class to define the Locale

If you want to define the user's locale, you can use the java.util.Locale class.

Common methods of Locale class
Set the language and country code to be used: public Locale(String language,String country) structure
Get the Locale class object of the current Locale: public static Locale getDefault()

package com.cj;
import java.util.Locale;

public class Person {
    public static void main(String[] args)throws Exception {
        Locale locale = Locale.getDefault();  //Gets the Local default Local object
        System.out.println(locale);

    }
}
Operation results:
zh_CN
//zh indicates that the language used is Chinese, CN indicates that the country is China
6. Use ResourceBundle to read resource files

Generally, resource files save text information in the form of "key, value", so that when reading information, the corresponding value data can be obtained according to the specified key. The name of resource files is required, and "*. properties" must be used as the suffix of the file. It can be completed by using java.util.ResourceBundle class.

Common methods of ResourceBundle class
According to the current default locale, get the resource bundle: getBundle()
Obtain the resource object (ResourceBundle): getbundle (string basename, locale, locale) according to the specified locale
Get the corresponding value data (String) according to the key: getString(Sgring key)

package com.cj;

import java.util.ResourceBundle;
//info = www.cj.com
public class Person {
    public static void main(String[] args)throws Exception {
//        You need to define a Message.properties file yourself
        //At this time, the Message.properties must be placed under the CLASSPATH
        ResourceBundle resourceBundle = ResourceBundle.getBundle("com.cj.Message");
        System.out.println(resourceBundle.getString("info"));
    }
}

Operation results:
www.cj.com

In fact, placeholders can be notified to adopt dynamic content settings in resource files, which must be completed by java.text.MessageFormat. The method of setting placeholders is: public static String format(String pattern,Object...arguments)

package com.cj;

import java.text.MessageFormat;
import java.util.ResourceBundle;
/*
* info = More access: {0}, Lecturer: {1}
* info = \sss\ssss\s\s\s\s{0}\s\s{1}
* */
public class Person {

    public static void main(String[] args)throws Exception {
//        You need to define a Message.properties file yourself
        //At this time, the Message.properties must be placed under the CLASSPATH
        ResourceBundle resourceBundle = ResourceBundle.getBundle("com.cj.Message");
        System.out.println(MessageFormat.format(resourceBundle.getString("info"),"www.cj.com","Sonorous"));
    }
}



Keywords: Java

Added by wacook on Fri, 26 Nov 2021 21:32:55 +0200