[TOC]

We’ve already looked at reflection, a common technique for frameworks in Java. You can say that reflection facilitates our development. Today we’re going to talk about his weaknesses, or we’re going to make it convenient on the basis of reflection.

Reflection operation method

In the previous chapter, we learned how to call methods through reflection.

public class App {
    public void test(String str, Integer integer) {
        System.out.println(str);
        System.out.println(integer); }}Copy the code

This is what I should do if I want to get the test method object at this point

Method testMethod = App.class.getMethod("test", String.class, Integer.class);
Copy the code

I won’t bother here with how to call a Method from a Method object. The address of the previous section is given at the end of the article. Today we are going to look at how methods get Method parameters. It seems so simple and yet so legendary. Let’s take a look at the following code execution

public static void main(String[] args) throws ParseException, NoSuchMethodException {
        Method[] methods = App.class.getMethods();
        Method testMethod = App.class.getMethod("test", String.class, Integer.class); Class<? >[] parameterTypes =testMethod.getParameterTypes();
        Parameter[] parameters = testMethod.getParameters();
        for(Parameter parameter : parameters) { System.out.println(parameter.getName()); }}Copy the code

So what are the two parameter names for the output? At first, I thought it was STR, name. I believe that you should think STR name as I do.

Arg0, arg1, arg0, arg1. That’s weird. And why? I don’t want to tell you just yet. I’ll tell you all about it.

Advantages of Spring’s approach

If you have done Javaweb development, you must have used spring, springmvc, when writing controller layer, we will write the name of the key value directly in the method, and then assign the corresponding key value in the request address.

@RequestMapping(value = "/deptId", method = RequestMethod.GET)
public PagedResult<SysDept> selectSysDeptsByPK(Integer pageNumber, Integer pageSize) {
    return sysDeptService.selectSysDeptsByPK(deptId, pageNumber,  pageSize);
}

Copy the code

For the controller above, we send http://{ip}:{port}/{projectName}/deptId after the request is sent from the front end. pageNumber=1&pageSize=5

I’m just wondering if you’ve ever wondered why springMVC is able to go through the parameters that you pass? We tried above that it is not possible to get method parameter names through reflection. Springmvc is all about reflecting action methods. Isn’t it amazing here, I have to admire the power of SpringMVC. Powerful enough to be feared.

How does reflection implement Spring’s methods

The two examples above expose the shortcomings of reflection and the power of SpringMVC. ParameterNameDiscoverer is a tool provided by SpringMVC. This class is just the discovery parameter name. Before we use this class, let’s look at why reflection doesn’t get method names.

The reason why Java can be cross-container is that Java provides different JVMS for different systems, so we need to install different versions of JDK before development. JDK provides THE JVM, and Java code is run through the JVM to operate on class files. But we usually develop Java files. So there is a compile period before the JVM executes. Javac is used to mutate Java files into class files.

package com.zxhtom.test;

/**
 * Hello world!
 */
public class App {
    public void test(String str, Integer integer) {}}Copy the code

For the above code let’s use javac to compile to see the effect. When javac app. Java is compiled, a class file with the same name appears

Javap-verbose app.class javap-verbose app.class

private static final ParameterNameDiscoverer parameterNameDiscoverer = new LocalVariableTableParameterNameDiscoverer();
public static void main(String[] args) throws ParseException, NoSuchMethodException {
    java.lang.reflect.Method testMethod = App.class.getMethod("test", String.class, Integer.class);
    String[] parameterNames = parameterNameDiscoverer.getParameterNames(testMethod);
    for(String parameterName : parameterNames) { System.out.println(parameterName); }}Copy the code

ParameterNameDiscoverer
ParameterNameDiscoverer
ParameterNameDiscoverer
DefaultParameterNameDiscoverer
PrioritizedParameterNameDiscoverer
PrioritizedParameterNameDiscoverer
addDiscoverer
PrioritizedParameterNameDiscoverer

  • KotlinReflectionParameterNameDiscoverer: Spring5.0 provides, but also get jdk8 and above version is used
  • StandardReflectionParameterNameDiscoverer: Spring4.0 provides, but also get jdk8 and above version is used
  • LocalVariableTableParameterNameDiscoverer: Spring2.0 had, the JDK versions do not have what request, Spring fully realize acquisition field names, logic is complicated, the efficiency is slightly lower

To summarize, before springmvc4.0, springmvc used its own set of code to obtain bytecode and analyze it. I’m not going to do the analysis because I’m limited here. Since 4.0, this bug has been remedied with the introduction of Java8. Springmvc also uses the function provided by JDK to get parameter names. Let’s take a look at how JDK8 solves this problem.

Java bytecode

In the previous section, we compiled Java through the javac, javap command. We found that the class bytecode records information in constant fields, classes, methods, where the code records location, heap, stack, line number, and so on. This is how we tune our JVM. But this is just our compilation using simple Javac.

Javac-g: Compile more comprehensively

The name of the explain
LineNumberTable Property table to store method row number information
LocalVariableTable The property table holds the local variable information for a method

The LocalVarableTable in the javac-g compiled information above has three pieces of data because every non-static method takes this as its first argument at compile time. Subtract the first one and all we’re left with is the parameter information we need. But let’s go ahead and see what happens.

Advanced reflection points

The advanced reflection is the JDK version requirement. As long as the JDK version is JDK8, you can use the JDK provided parameter method to obtain the parameter name. -parameters is required at compile time

Javac Easter eggs

Continue to point

## Laugh of the Day

Today the company has a holiday, with the wife to discuss together go to her home, departure eve, the wife say: give my family’s gift buy good yao? Then I went to the bedroom and moved it all out; Give her to say: this is your uncle, this is your uncle, this is your grandpa, this is your grandma, this is your dad, this is your mom, this is ………… And then we got into a fight!

The answer of the previous period

There is no

Wechat official account