Analysis of obtaining method parameter names in JAVA (1). Obtaining method parameters in java
Questions
First, let's explain the question. We know that through reflection, Java can know from a class what it hasMethod, WhichVariableYou can also know which typesInput parameters. But there is one thing that cannot be reflected, that is, the name of the input parameter of the method.
What is the significance of obtaining the name of an input parameter?
The exploration of this problem stems from the need to write a test class. Suppose we have a class that needs to be tested. There are dozens of methods in this class. Writing a test class for each method takes a lot of time and effort. Therefore, I have an idea that all methods of this class are obtained through java reflection, and some data that meets the requirements is generated by passing in the parameter name and parameter type. (The premise for generating data in this way is that the class encoding must follow strict standards and have uniform parameter naming standards. At the same time, this class should be closely related to a certain service, in this way, you can determine the appropriate data to be generated through the business and parameter names ). If you can do the above, you only need to pass in this class to classes with dozens or hundreds of methods to test.
Problems
According to the above assumptions, the problem arises. Obtain the method of the class, obtain the parameter type of the class, and perform reflection. But what about the parameter name? Online verification, most people give a direct negative answer. Because the API does not provide relevant methods at all. But some people have inspired me. They mentioned that when calling a class method in the coding process in IDE (such as eclipse and myeclipse), ide can display the parameter names in the method when the Code prompts, such:
How does IDE do it? If IDE can do it, can we try to analyze them to get the parameter name.
Possible practices
We found a very intuitive method on the Internet-Directly Reading The. java file, taking the class as a common text, and using the regular expression matching method to directly obtain the parameter name.
Java code
- /**
- * @ Author zhangc
- *
- * A test program is used to scan files (java files) and locate the parameter list of all methods
- */
- Import java. io .*;
- Import java. util. regex .*;
- Public class ScanSource {
- Static void findArgsList (Object targetSrc ){
- /*
- * Regular Expression matching strings are basically grouped in this way (A (B (c (d ))))
- * String: (\ w + \ s + \ w + \ s * \ (\ s * \ w + \ s *(\\ [
- * \]) * \ S + (\ [\]) * \ s * \ w + \ s * (\ [\]) *,?) +) \ S * \ {) such as public
- * Static void findArgsList (Object targetSrc, int [] ){
- * A is the definition line matching the entire method: here is: static void findArgsList (Object targetSrc, int [] ){
- * B indicates the list of matched parameters. Here, Object targetSrc, int []
- * C is a matching parameter, including the type and type name and comma: Here is the Object targetSrc, D is the matching array identifier: Here is []
- * This string is a bit bt and has a limited level. This is the only option.
- */
- Pattern p = Pattern
- . Compile ("(\ w + \ s + \ w + \ s * \ (\ s * \ w + \ s *(\\ [\]) * \ s + (\ [\]) * \ s * \ w + \ s * (\ [\]) *,?) +) \ S *\\{)");
- Matcher m = p. matcher (CharSequence) targetSrc );
- // Locate the all methord defination
- While (m. find ()){
- String methodName = m. group (0 );
- String methodArgName = m. group (1 );
- String strArgs = m. group (2 );
- String fourArgs = m. group (3 );
- System. out. println (methodName + "\ n" + methodArgName + "\ n" + strArgs + "\ n" + fourArgs + "\ n ");
- }
- }
- Public static String LoadTargetFile (String targetFileName ){
- String result = null;
- Try {
- FileInputStream FCM = new FileInputStream (targetFileName );
- // Temporarily allocate the bytes size to the byte array.
- Byte [] bufReceived = new byte [10000];
- Int counts = FS. read (bufReceived );
- Byte [] bufActual = new byte [counts];
- System. arraycopy (bufReceived, 0, bufActual, 0, counts );
- Result = new String (bufActual );
- } Catch (FileNotFoundException e ){
- E. printStackTrace ();
- } Catch (IOException e ){
- E. printStackTrace ();
- }
- Return result;
- }
- Public static void main (String [] args ){
- String target = LoadTargetFile ("src/com/spring/aop/TestAspect. java ");
- System. out. println (target );
- FindArgsList (target );
- }
- }
In a simple test class I wrote using regular expressions, the value of the parameter can be obtained, however, when we use it in a class with dozens of methods, expression matching becomes invalid and no result is obtained (the specific cause may be a regular expression error, failed to match some methods ). At the same time, this method requires the. java source file, which is often a Jar package composed of. class introduced in IDE. To further understand how IDE processes the parameter names passed in to the method, I will perform a test below.
Processing of method input parameters by test IDE
Create a project. Create the following class in the project:
Java code
- Package testplugin;
- Public class TestJar {
- Public void testJar (String jarName, String yourName ){
- System. out. println ("jarName:" + jarName + "| yourName:" + yourName );
- }
- }
Then we use two methods to pack the jar package for this class:
1. Use javac to compile the class file and call it to the jar package. Name it testPlugin_javac.jar.
2. Export the project directly using MyEclipse and export it as testPlugin_myeclipse.jar.
(Open the TestJar. class file in two jar files, and you will find two class files are different ).
Create another project and import two jar packages to the experiment. You can see:
1. Introduce testPlugin_javac.jar and call the testJar method, as shown in figure
We can see that the original names of the two input parameters are lost.
2. Remove the preceding package, introduce testPlugin_myEclipse.jar, and call the testJar method, as shown in figure
We can see that the parameter name is identified.
The key is that the class files in the two jar packages are different. We open two class files (we just look at the variables in the class file intuitively, so we didn't use dedicated tools to view them ):
. Class generated by javac:
Myelipse directly calls. class (actually called. class compiled in debug mode ):
The following parts of the two class files contain the SourceFile block. It should be used to indicate the java file from which the class file is compiled. Let's focus on the above section.
As you can see, the passed Parameter Name of the method will be modified by the compiler using a normal javac compiled class. Therefore, the jarName and yourName cannot be found in the first SourceFile or above. The parameter name of a class compiled in-debug mode can be saved. In other words, the. class file contains a jar package with a reserved parameter name. Only after the code prompts In the IDE can the parameter name be correctly displayed.
Whether the IDE can identify the method names in the class depends on the different class files generated after compilation. In the next section, we will use tools to parse the two class files to see what is the difference.
I want to write a java file to parse another java source file to quickly display the parameter names corresponding to all method names and methods.
Class <?> Clazz = Class. forName ("com. test. Cal ");
For (Method method: clazz. getMethods ()){
System. out. print ("Method:" + method. getName ());
For (Class <?> ParamClass: method. getParameterTypes ()){
System. out. print ("\ t" + paramClass. getName () + ",");
}
System. out. println ();
}
The above is probably the answer you need. Only the parameter type can be obtained. After all, the form parameter name is actually useless.
How can I get the parameter value of another method by writing a method in java?
Class
{
Public String methodA (String)
{
Return;
}
Public void methodB ()
{
String B = methodA ();
}
}