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); // 获取方法返回类型的全限定名

    }
}

在这里插入图片描述



本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/920443.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2024亚太杯国际赛C题宠物预测1234问完整解题思路代码+成品参考文章

中国宠物业发展趋势及预测模型 一、问题背景与研究目标 近年来&#xff0c;中国宠物业经历了快速发展&#xff0c;特别是在城市化进程加快、人口结构变化和消费水平提升的背景下&#xff0c;宠物作为家庭成员的角色变得愈发重要。根据相关数据&#xff0c;中国宠物数量&#…

Java实现离线身份证号码OCR识别

最近公司要求做离线身份证OCR功能&#xff0c;找了一圈总算是找到了&#xff0c;在这里对文档做个整理&#xff0c;方便后来者&#xff0c;感谢码龄23年博主的分享 系统&#xff1a;Windows11&#xff0c;红旗Linux Asianux8.1 文档中Linux全root用户操作&#xff1b;需先安装…

Gradle核心概念总结

这部分内容主要根据 Gradle 官方文档整理&#xff0c;做了对应的删减&#xff0c;主要保留比较重要的部分&#xff0c;不涉及实战&#xff0c;主要是一些重要概念的介绍。 Gradle 这部分内容属于可选内容&#xff0c;可以根据自身需求决定是否学习&#xff0c;目前国内还是使用…

鸿蒙网络编程系列50-仓颉版TCP回声服务器示例

1. TCP服务端简介 TCP服务端是基于TCP协议构建的一种网络服务模式&#xff0c;它为HTTP&#xff08;超文本传输协议&#xff09;、SMTP&#xff08;简单邮件传输协议&#xff09;等高层协议的应用程序提供了可靠的底层支持。在TCP服务端中&#xff0c;服务器启动后会监听一个或…

第5-1节:SpringBoot对SpringMVC的自动配置

我的后端学习大纲 SpringBoot学习大纲 1、SpringBoot对SpringMVC自动配置概览

Emacs进阶之插入时间信息(一百六十三)

简介&#xff1a; CSDN博客专家、《Android系统多媒体进阶实战》一书作者 新书发布&#xff1a;《Android系统多媒体进阶实战》&#x1f680; 优质专栏&#xff1a; Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a; 多媒体系统工程师系列【…

嵌入式实验报告:家用计时器

实验目的和要求 1、实验目的 掌握STM32串口通信原理。学习编程实现STM32的UART通信掌握STM32中断程序设计流程。熟悉STM32固件库的基本使用。熟悉STM32定时器中断设计流程。2、实验要求 设计一个家用计时器,其功能如下: 利用串口设置计时时间,格式:XX:XX:X 例如01:59:…

【WRF理论第十二期】Registry.EM 文件详解

【WRF理论第十二期】Registry.EM 文件详解 Registry.EM 文件的作用Registry.EM 文件的结构Registry.EM 文件内容理解如何修改 Registry.EM 文件以输出特定变量WRF-Urban 修改 Registry.EM 文件以输出 UCM 相关变量1. 修改 Registry.EM 文件2. 重新编译 WRF 注意事项参考 在 WRF…

Midjourney 图生图,真人二次元保持一致性,场景多元可选择

Midjourney 拥有强大的图生图的功能&#xff0c;下面我们就来看一下&#xff0c;如何在我们的AceDataCloud网站上实现将照片切换成任意的二次元场景&#xff0c;同时保持人物的一致性。 我们可以按照如下的步骤去实现人物一致性。 下面我们来看看效果吧&#xff0c;原图如下。…

三种复制只有阅读权限的飞书网络文档的方法

大家都知道&#xff0c;飞书是一款功能强大的在线协作工具&#xff0c;可以帮助团队更高效地协作和沟通。越来越多的资料都在使用飞书文档&#xff0c;在使用飞书的过程中&#xff0c;发现很多文档没有复制权限&#xff0c;如果想要摘抄笔记&#xff0c;只能一个字一个字地敲出…

【GL003】TCP/IP 协议

目录 一、TCP/IP协议简介 二、TCP/IP协议的分层模型 2.1 OSI模型的七层框架 2.2 TCP/IP协议层&#xff08;四层&#xff09; 2.2.1 TCP/IP协议层与ISO模型 2.2.2 TCP/IP协议层的作用 三、TCP协议的报文格式 3.1 什么是报文 3.2 TCP报文 四、TCP的通信连接 4.1 TCP…

Spring WebFlux学习笔记(二)

目标 运行第一个spring webflux项目 官网操作 https://start.spring.io/ 依赖、工具 jdk 21、idea、maven 运行过程 将下载的代码直接导入到idea后运行 运行上个笔记的例子 注意 需要更改为MediaType.TEXT_EVENT_STREAM_VALUE 未完待续。。。

【YOLOv8】安卓端部署-2-项目实战

文章目录 1 准备Android项目文件1.1 解压文件1.2 放置ncnn模型文件1.3 放置ncnn和opencv的android文件1.4 修改CMakeLists.txt文件 2 手机连接电脑并编译软件2.1 编译软件2.2 更新配置及布局2.3 编译2.4 连接手机 3 自己数据集训练模型的部署4 参考 1 准备Android项目文件 1.1…

基于CNN-LSTM的时序预测MATLAB实战

卷积神经网络&#xff08;CNN&#xff09;用于提取时间序列数据中的局部空间特征&#xff0c;通过卷积层和池化层的堆叠&#xff0c;CNN能够有效捕获数据中的短期模式和局部依赖关系。长短时记忆网络&#xff08;LSTM&#xff09;用于处理时间序列数据&#xff0c;特别擅长捕捉…

3D可视化产品定制,打造“所见即所得”的购物体验!

在当今数字化时代&#xff0c;3D可视化产品定制正逐步改变着消费者的购物体验与企业的销售模式&#xff0c;相较于大多仍停留在二维层面的线上定制服务&#xff0c;3D可视化产品定制为消费者提供了一个直观、互动且高度个性化的定制功能&#xff0c;并为消费者带来了沉浸式的购…

捉虫记录02-Nacos访问失败

目录 一、问题 二、排查 三、解决方案 一、问题 在访问nacos的时候出现以下问题&#xff1a; 二、排查 先用docker logs nacos来查找报错信息 docker logs nacos 看问题报错就是数据源问题&#xff0c;nacos没能连接上mysql 三、解决方案 第一步 docker restart mysql …

详细教程-Linux上安装单机版的Hadoop

1、上传Hadoop安装包至linux并解压 tar -zxvf hadoop-2.6.0-cdh5.15.2.tar.gz 安装包&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1u59OLTJctKmm9YVWr_F-Cg 提取码&#xff1a;0pfj 2、配置免密码登录 生成秘钥&#xff1a; ssh-keygen -t rsa -P 将秘钥写入认…

桌面怎么快速添加便签?适合桌面记事的便签小工具

在数字化时代&#xff0c;我们每天面对电脑处理大量任务&#xff0c;无论是工作计划、会议纪要还是个人生活琐事&#xff0c;都需要一个可靠的桌面记事工具来帮助我们记录和整理。因此&#xff0c;一款适合桌面使用的便签软件成为了我们不可或缺的助手。 敬业签就是这样一款功…

Django实现智能问答助手-基础配置

设置 Django 项目、创建应用、定义模型和视图、实现问答逻辑&#xff0c;并设计用户界面。下面是一步一步的简要说明&#xff1a; 目录&#xff1a; QnAAssistant/ # 项目目录 │ ├── QnAAssistant/ # 项目文件夹 │ ├── init.py # 空文件 │ ├── settings.py # 项目配…

Python的3D可视化库 - vedo (2)visual子模块 基本可视化行为

文章目录 1. visual模块的继承关系2. 基类CommonVisual的方法2.1 获取对象信息2.1.1 对象本身信息2.1.2 对象的查找表2.1.3 对象标量范围2.1.4 对象缩略图 2.2 呈现对象2.2.1 在窗口显示1.2.2 对象可见性 2.2.3 对象颜色2.2.4 对象透明度 2.3 添加标度条2.3.1 2D标度条2.3.2 3D…