Java reflection mechanism live example sharing

  • 2020-04-01 03:01:04
  • OfStack

First, let's recognize a few classes.

Class (Java. Lang. Class)

A Class object is a special object, and each Class has a Class object to create a "regular" object for that Class. You can get it through the object's getClass() method.

Let's say we run this line of code:


System.out.println(" test ".getClass().toString());

The result is:


class java.lang.String
Field(java.lang.reflect.Field)

This class represents a field that can be used to access the class

Now, let's create the test class:


class Book {
    public String title;
    public int length = 0;
    public ArrayList<Page> pages = null;
    @Override
    public String toString() {
        String sb = "Book:n";
        sb += "title="+title+"n";
        sb += "length=" + length + "n";
        sb += "pages=" + pages + "n";
        if (pages != null) {
            for (Page page : pages) {
                sb += page.toString();
            }
        }
        return sb.toString();
    }
}
class Page {
    @Override
    public String toString() {
        return "pagen";
    }
}

Call the following methods to test the above class:


Book book = new Book();
System.out.println(book);

The result:


Book:
title=null
length=0
pages=null

This is the initial state of the book object

Let's get the length field in the book object and modify it through reflection to see the results:


Book book = new Book();
Class<?> aClass = book.getClass();
Field field = aClass.getField("length");
field.setInt(book, 9);
System.out.println(book);

You can see that the result of the operation is:


Book:
title=null
length=9
pages=null


As you can see, the value of the length field has been changed.

The above modification is a simple field of int type. In fact, an object field like the title field can also be modified. Here is an example:


Book book = new Book();
Class<?> aClass = book.getClass();
Field[] fields = aClass.getFields();
for (Field field : fields) {
    field.setAccessible(true);
    if(field.getType().equals(String.class)){
        field.set(book, " Grimm's fairy tales ");
    }else if(field.getType().equals(int.class)){
        field.set(book, 199);
    }
}
System.out.println(book);

The output of the above code is:


Book:
title= Grimm's fairy tales 
length=199
pages=null

In fact, all String fields are changed to "Grimm's fairy tale" and all int fields are changed to 199. We don't even know what this field means.

Next, we modify the field of pages. This field is an ArrayList, and we will create an ArrayList object and insert an object into it.


Book book = new Book();
Class<?> aClass = book.getClass();
Field[] fields = aClass.getFields();
for (Field field : fields) {
    field.setAccessible(true);
    if(field.getType().equals(ArrayList.class)){
        String genric = field.getGenericType().toString();
        String genricClass = genric.substring(
                            genric.indexOf('<') + 1,
                            genric.indexOf('>'));
        Class<?> entityClass = Class.forName(genricClass);
        Object obj = entityClass.newInstance();
        ArrayList list = new ArrayList();
        list.add(obj);
        field.set(book, list);
        }
    }
System.out.println(book);

The output results are as follows:


Book:
title=null
length=0
pages=[page
]
Page

As you can see, we created a Page object even though we didn't use the Page class directly at all.

The creation statement of Page object is in: entityclass.newinstance (). The newInstance statement is an important method of the Class object, which is used to create the object corresponding to this Class. Of course, the class's constructor support is required. In addition, through the genGenericType method, we can get the type modifier of the field. If you put it here, you get an ArrayList< Page> . With this string, we can load the Page Class and create a Page object through the classloader class.forname.


Related articles: