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

news2024/11/22 12:33:18

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

    }
}

在这里插入图片描述



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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

25.UE5时间膨胀,慢动作,切换地图,刷BOSS

2-27 时间膨胀、慢动作、切换地图、刷BOSS_哔哩哔哩_bilibili 目录 1.刷新BOSS逻辑 2.时间膨胀实现慢动作 3.胜利画面&#xff0c;下一关 3.1胜利画面UI 3.2第一关、第二关游戏模式 3.3下一关按钮事件的绑定 1.刷新BOSS逻辑 实现当场上的怪物都死亡后&#xff0c;进行刷…

【大语言模型】ACL2024论文-19 SportsMetrics: 融合文本和数值数据以理解大型语言模型中的信息融合

【大语言模型】ACL2024论文-19 SportsMetrics: 融合文本和数值数据以理解大型语言模型中的信息融合 https://arxiv.org/pdf/2402.10979 目录 文章目录 【大语言模型】ACL2024论文-19 SportsMetrics: 融合文本和数值数据以理解大型语言模型中的信息融合目录摘要研究背景问题与挑…

数字IC后端设计实现之Innovus place报错案例 (IMPSP-9099,9100三种解决方案)

最近吾爱IC社区星球会员问到跑place_opt_design时会报错退出的情况。小编今天把这个错误解决办法分享给大家。主要分享三个方法&#xff0c;大家可以根据自己的实际情况来选择。 数字IC后端低功耗设计实现案例分享(3个power domain&#xff0c;2个voltage domain) **ERROR: (I…

弧形导轨有什么优势及局限?

弧形导轨的设计允许负载沿着特定的曲线路径移动&#xff0c;这在许多自动化设备中是非常必要的。它具有高强度、刚性和稳定性&#xff0c;能够承受较大的负载和冲击力&#xff0c;并且在高速运动下仍能保持稳定&#xff0c;这使得弧形导轨在需要处理重型负载或进行高速运动的场…

【天壤智能-注册安全分析报告-无验证纯IP限制存在误拦截隐患】

前言 由于网站注册入口容易被机器执行自动化程序攻击&#xff0c;存在如下风险&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露&#xff0c;不符合国家等级保护的要求。短信盗刷带来的拒绝服务风险 &#xff0c;造成用户无法登陆、注册&#xff0c;大量收到垃圾短信的…

Linux13 传输层UDP和TCP协议

传输层UDP和TCP协议 1. UDP 协议1.1 UDP协议端格式1.2 UDP特点1.3 UDP 的缓冲区1.4 UDP数据长度1.5 基于 UDP 的应用层协议 2. TCP 协议TCP协议端格式确认应答序号和确认序号位通信机制&#xff1a; 超时重传连接管理三次握手 - 建立连接三次握手与TCPSocket问题 - 为什么要有三…

Figure 02迎重大升级!!人形机器人独角兽[Figure AI]商业化加速

11月19日知名人形机器人独角兽公司【Figure AI】发布公司汽车巨头【宝马】最新合作进展&#xff0c;旗下人形机器人Figure 02在生产线上的性能得到了显著提升&#xff0c;机器人组成自主舰队&#xff0c;依托端到端技术&#xff0c;速度提高了400%&#xff0c;执行任务成功率提…

OpenCV 图片处理与绘制

目录 1. 图片处理 1.1 灰度处理 1.1.1 图像灰度化处理 1.1.2 图像灰度化的算法 1.2 图像二值化 1.3 边缘检测 ​编辑 2. 绘图 2.1 绘制线段 2.2 绘制矩形 2.3 绘制圆形 2.4 绘制椭圆 2.5 绘制多边形 2.6 绘制文字图片 1. 图片处理 1.1 灰度处理 将彩色图像转化为…

uniapp 城市选择插件

uniapp城市选择插件 如上图 地址 完整demo <template><view><city-selectcityClick"cityClick":formatName"formatName":activeCity"activeCity":hotCity"hotCity":obtainCitys"obtainCitys":isSearch&quo…

实验室资源调度系统:基于Spring Boot的创新

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统&#xff0c;它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等&#xff0c;非常…

【Triton 教程】融合注意力 (Fused Attention)

Triton 是一种用于并行编程的语言和编译器。它旨在提供一个基于 Python 的编程环境&#xff0c;以高效编写自定义 DNN 计算内核&#xff0c;并能够在现代 GPU 硬件上以最大吞吐量运行。 更多 Triton 中文文档可访问 →https://triton.hyper.ai/ 这是根据 Tri Dao 的 Flash At…

近源渗透|HID ATTACK从0到1

前言 对于“近源渗透”这一术语&#xff0c;相信大家已经不再感到陌生。它涉及通过伪装、社会工程学等手段&#xff0c;实地侵入企业办公区域&#xff0c;利用内部潜在的攻击面——例如Wi-Fi网络、RFID门禁、暴露的有线网口、USB接口等——获取关键信息&#xff0c;并以隐蔽的…

大数据入门-什么是Flink

这里简单介绍Flink的概念、架构、特性等。至于比较详细的介绍&#xff0c;会单独针对这个组件进行详细介绍&#xff0c;可以关注博客后续阅读。 一、概念 Apache Flink 是一个框架和分布式处理引擎&#xff0c;用于在无边界和有边界数据流上进行有状态的计算。 Flink的四大基…

Excel如何批量导入图片

这篇文章将介绍在Excel中如何根据某列数据&#xff0c;批量的导入与之匹配的图片。 准备工作 如图&#xff0c;我们准备了一张员工信息表以及几张员工的照片 可以看到&#xff0c;照片名称是每个人的名字&#xff0c;与Excel表中的B列&#xff08;姓名&#xff09;对应 的卢易…

9个最佳WordPress PDF插件(查看器、嵌入和下载)

在过去的几年里&#xff0c;我们一直在使用不同的 PDF 插件在我们的网站上创建、编辑和嵌入文档。 然而&#xff0c;经过多次尝试和错误&#xff0c;我们意识到并不是每个插件都是相同的。事实上&#xff0c;为您的企业或电子商务网站选择合适的 PDF 插件可能是一项艰巨的任务…

java-贪心算法

1. 霍夫曼编码&#xff08;Huffman Coding&#xff09; 描述&#xff1a; 霍夫曼编码是一种使用变长编码表对数据进行编码的算法&#xff0c;由David A. Huffman在1952年发明。它是一种贪心算法&#xff0c;用于数据压缩。霍夫曼编码通过构建一个二叉树&#xff08;霍夫曼树&a…

Seatunnel运行时报错Caused by: java.lang.NoClassDefFoundError: com/mysql/cj/MysqlType

报错 [] 2024-11-21 16:46:27,526 ERROR org.apache.seatunnel.core.starter.SeaTunnel - Fatal Error, [] 2024-11-21 16:46:27,526 ERROR org.apache.seatunnel.core.starter.SeaTunnel - Please submit bug report in https://github.com/apache/seatunnel/issues[] 2024-11…

vue自定义指令--一键复制

vue项目中想要实现点击按钮一键复制&#xff0c;可以通过vue的自定义指令directive来实现。 一、新建directive.js文件 新建directive.js文件&#xff0c;用于定义所有的自定义指令。 import { Toast } from vant;const directive {// 一键复制copy:{bind (el, { value }) …

AI 大模型重塑软件开发的未来

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

python: generator model using sql server 2019

設計或生成好數據庫&#xff0c;可以生成自己設計好的框架項目 # encoding: utf-8 # 版权所有 &#xff1a;2024 ©涂聚文有限公司 # 许可信息查看 &#xff1a;言語成了邀功盡責的功臣&#xff0c;還需要行爲每日來值班嗎 # 描述&#xff1a; : 生成实体 # Author …