0
点赞
收藏
分享

微信扫一扫

JavaParser如何获取方法的返回类型

使用JavaParser 如何获取一个Java类中的某个方法的返回类型呢?
假如有一个如下的简单的Java 类:


/**
 * Copyright (C)  Oscar Chen(XM):
 * 
 * Date: 2024-11-21
 * Author: XM
 */
package com.osxm.ai.sdlc.codeparse.codesample;

public class MyClass {
    public String myMethod(String str) {
        return str;
    }
}

  • 该类有一个返回String 类型的方法myMethod()

使用JavaParser 如何获取myMethod的返回类型,也就是String 呢?

获取方法的返回类型类的简化名

这里直接给实现代码:

    // @formatter:off
    String sourceCode = "public class MyClass {" +
                          "public String myMethod(String str){" +
                              "return str;" +
                           "}" +
                        "}";
    // @formatter:on

    @Test
    public void methodReturnClassSimpleName() {
        CompilationUnit cu = StaticJavaParser.parse(sourceCode);
        String methodName = "myMethod";
        MethodDeclaration methodDecl = cu.findAll(MethodDeclaration.class).stream()
                .filter(md -> md.getName().getIdentifier().equals(methodName))
                .findFirst()
                .orElseThrow(() -> new RuntimeException("Method not found"));

        Type returnType = methodDecl.getType();
        String returnSimpleClassName = returnType.asString();
        Assertions.assertEquals("String", returnSimpleClassName); // 获取方法返回类型的简化名
    }

代码解释如下:

  1. CompilationUnit cu = StaticJavaParser.parse(sourceCode);
    • 这行代码使用JavaParser库来解析给定的Java源代码字符串sourceCode,并将其转换为一个CompilationUnit对象。CompilationUnit是JavaParser中表示整个Java源文件的一个抽象语法树(AST)的根节点。
  2. String methodName = "myMethod";
    • 这行代码定义了一个字符串变量methodName,并将其值设置为"myMethod"。这是要查找的方法的名称。
  3. MethodDeclaration methodDecl = cu.findAll(MethodDeclaration.class).stream()
    • 这行代码开始通过cu(即CompilationUnit对象)查找所有的方法声明(MethodDeclaration)。findAll(MethodDeclaration.class)返回一个包含所有方法声明的列表。
    • .stream()将这个列表转换为一个流(Stream),以便进行后续的流式处理。
  4. .filter(md -> md.getName().getIdentifier().equals(methodName))
    • 这行代码使用filter方法过滤流中的元素。它保留那些其名称(通过md.getName().getIdentifier()获取)等于methodName(即"myMethod")的方法声明。
  5. .findFirst()
    • 这行代码尝试从过滤后的流中找到第一个元素(即第一个匹配的方法声明)。如果找到,它返回一个包含该元素的Optional<MethodDeclaration>;如果没有找到,它返回一个空的Optional
  6. .orElseThrow(() -> new RuntimeException("Method not found"));
    • 这行代码处理上一步返回的Optional。如果Optional是空的(即没有找到方法),则执行orElseThrow,抛出一个RuntimeException,异常信息为"Method not found"。如果Optional非空,即找到了方法,则将其值(MethodDeclaration对象)赋给methodDecl变量。
  7. Type returnType = methodDecl.getType();
    • 这行代码获取methodDecl(即找到的myMethod方法)的返回类型,并将其存储在returnType变量中。
  8. String returnSimpleClassName = returnType.asString();
    • 这行代码将returnType(即方法的返回类型)转换为其字符串表示形式,这里返回的是简化名。
  9. Assertions.assertEquals("String", returnSimpleClassName);
    • 这行代码使用JUnit的Assertions类来断言returnSimpleClassName(即方法的返回类型的字符串表示)是否等于字符串"String"。这是为了验证myMethod方法的返回类型确实是String

现在问题来了, 如果要返回全限定名, 也就是这里的java.lang.String 要怎么处理呢?

获取方法的返回类型类的全限定名

同样,直接上代码:

    @Test
    public void methodReturnClassFullName() {
        ReflectionTypeSolver reflectionTypeSolver = new ReflectionTypeSolver();
        JavaSymbolSolver symbolSolver = new JavaSymbolSolver(reflectionTypeSolver);
        // init parser
        ParserConfiguration configuration = new ParserConfiguration().setSymbolResolver(symbolSolver);
        // Setup parser
        StaticJavaParser.setConfiguration(configuration);

        CompilationUnit cu = StaticJavaParser.parse(sourceCode);
        String methodName = "myMethod";
        MethodDeclaration methodDecl = cu.findAll(MethodDeclaration.class).stream()
                .filter(md -> md.getName().getIdentifier().equals(methodName))
                .findFirst()
                .orElseThrow(() -> new RuntimeException("Method not found"));

        Type returnType = methodDecl.getType();
        String returnSimpleClassName = returnType.asString();
        Assertions.assertEquals("String", returnSimpleClassName); // 获取方法返回类型的简化名

        String fullClassName = returnType.resolve().describe();
        Assertions.assertEquals("java.lang.String", fullClassName); // 获取方法返回类型的全限定名

    }

**重点: ** 要便捷的获取全限定名, 需要结合 JavaSymbolSolver ,也就是JavaParser-Symbol-Solver 这个库来使用。

完整的解释:

  • ReflectionTypeSolver是JavaSymbolSolver库中的一个组件,它使用Java反射API来解析类路径上的Java类文件,以获取类型信息。
  • JavaSymbolSolver是一个更高级的组件,它使用TypeSolver(在这个例子中是ReflectionTypeSolver)来解决符号(如类型、方法等)的引用。
  • 这里创建了一个ParserConfiguration对象,并通过setSymbolResolver方法设置了之前创建的JavaSymbolSolver实例。
  • 然后,使用StaticJavaParser.setConfiguration方法将这个配置应用到JavaParser上。这样,当JavaParser解析源代码时,它就可以使用JavaSymbolSolver来解决符号引用了。
  • returnType.resolve().describe()返回类型的完全描述,这通常包括类型的完全限定名以及任何泛型信息。对于基本类型或String等常见类型,这将返回它们的完全限定名。

完整代码如下:

/**
 * Copyright (C)  Oscar Chen(XM):
 * 
 * Date: 2024-11-21
 * Author: XM
 */
package com.osxm.ai.sdlc.javaparser;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import com.github.javaparser.ParserConfiguration;
import com.github.javaparser.StaticJavaParser;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.body.MethodDeclaration;
import com.github.javaparser.ast.type.Type;
import com.github.javaparser.symbolsolver.JavaSymbolSolver;
import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;

public class MethodInfo {
    // @formatter:off
    String sourceCode = "public class MyClass {" +
                          "public String myMethod(String str){" +
                              "return str;" +
                           "}" +
                        "}";
    // @formatter:on

    @Test
    public void methodReturnClassSimpleName() {
        CompilationUnit cu = StaticJavaParser.parse(sourceCode);
        String methodName = "myMethod";
        MethodDeclaration methodDecl = cu.findAll(MethodDeclaration.class).stream()
                .filter(md -> md.getName().getIdentifier().equals(methodName))
                .findFirst()
                .orElseThrow(() -> new RuntimeException("Method not found"));

        Type returnType = methodDecl.getType();
        String returnSimpleClassName = returnType.asString();
        Assertions.assertEquals("String", returnSimpleClassName); // 获取方法返回类型的简化名
    }

    @Test
    public void methodReturnClassFullName() {
        ReflectionTypeSolver reflectionTypeSolver = new ReflectionTypeSolver();
        JavaSymbolSolver symbolSolver = new JavaSymbolSolver(reflectionTypeSolver);
        // init parser
        ParserConfiguration configuration = new ParserConfiguration().setSymbolResolver(symbolSolver);
        // Setup parser
        StaticJavaParser.setConfiguration(configuration);

        CompilationUnit cu = StaticJavaParser.parse(sourceCode);
        String methodName = "myMethod";
        MethodDeclaration methodDecl = cu.findAll(MethodDeclaration.class).stream()
                .filter(md -> md.getName().getIdentifier().equals(methodName))
                .findFirst()
                .orElseThrow(() -> new RuntimeException("Method not found"));

        Type returnType = methodDecl.getType();
        String returnSimpleClassName = returnType.asString();
        Assertions.assertEquals("String", returnSimpleClassName); // 获取方法返回类型的简化名

        String fullClassName = returnType.resolve().describe();
        Assertions.assertEquals("java.lang.String", fullClassName); // 获取方法返回类型的全限定名

    }
}

在这里插入图片描述



举报

相关推荐

0 条评论