You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java读取文本文件方法调用报NoSuchMethodException如何解决

报错根因

Class.getMethod()方法的合法入参是「目标类的方法名」+「方法形参类型列表」,不支持直接传入完整链式调用表达式。你把t.getP().getName()整串作为方法名传入,JVM会直接在Test类下找名为t.getP().getName()的无参方法,自然匹配不到,抛出NoSuchMethodException。

实现方案

根据场景复杂度选以下两种方案即可:

方案1:手动拆分链式调用反射执行(无额外依赖,适配简单getter场景)

核心逻辑是按.拆分每一行的调用链,逐段反射执行方法,上一段的返回值作为下一段调用的实例对象,直到走完整个链路。
实现代码如下:

import java.lang.reflect.Method;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

public class Test {
    private Person p;

    public Test(){
        p = new Person("Jhon", "19", "New York", "Mathematician");
    }

    public Person getP() {
        return p;
    }

    // 链式无参方法执行工具
    private static Object execChain(Object rootInstance, String express) throws Exception {
        Object current = rootInstance;
        String[] nodes = express.split("\\.");
        for (String node : nodes) {
            String trimNode = node.trim();
            // 跳过根变量名t,初始实例已经传入
            if ("t".equals(trimNode)) continue;
            // 提取方法名,去掉末尾括号
            String methodName = trimNode.replace("()", "");
            // 查找当前对象所属类的无参方法
            Method method = current.getClass().getMethod(methodName);
            // 执行方法,返回值作为下一轮调用的实例
            current = method.invoke(current);
        }
        return current;
    }

    public static void main(String[] args) throws Exception {
        Test t = new Test();
        // 读取Commands.txt文件
        List<String> allLines = Files.readAllLines(Paths.get("Commands.txt"));
        List<String> validExprs = new ArrayList<>();
        // 过滤无效行:大括号、空行
        for (String line : allLines) {
            String trimLine = line.trim();
            if (trimLine.isEmpty() || trimLine.equals("{") || trimLine.equals("}")) continue;
            validExprs.add(trimLine);
        }
        // 逐行执行并打印结果
        for (String expr : validExprs) {
            Object result = execChain(t, expr);
            System.out.printf("执行语句[%s],返回结果:%s%n", expr, result);
        }
    }
}

方案2:JDK脚本引擎直接执行表达式(适配复杂语句场景)

JDK8-14内置Nashorn JavaScript引擎,可以直接绑定Java对象执行链式表达式,不需要手动解析反射链路,代码更简洁。高版本JDK可单独引入Nashorn依赖使用。
核心实现代码如下:

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.SimpleBindings;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;

public class Test {
    private Person p;

    public Test(){
        p = new Person("Jhon", "19", "New York", "Mathematician");
    }

    public Person getP() {
        return p;
    }

    public static void main(String[] args) throws Exception {
        Test t = new Test();
        // 初始化脚本引擎
        ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
        SimpleBindings bindings = new SimpleBindings();
        // 把t对象绑定到脚本上下文
        bindings.put("t", t);
        // 读取过滤文件逻辑和方案1一致
        List<String> allLines = Files.readAllLines(Paths.get("Commands.txt"));
        for (String line : allLines) {
            String trimLine = line.trim();
            if (trimLine.isEmpty() || trimLine.equals("{") || trimLine.equals("}")) continue;
            Object result = engine.eval(trimLine, bindings);
            System.out.printf("执行语句[%s],返回结果:%s%n", trimLine, result);
        }
    }
}
注意事项
  • 方案1的简易实现仅适配示例中的无参getter场景,如果需要支持带参数方法、字段访问,需要补充表达式解析、参数类型匹配逻辑
  • 确保调用链上的所有类都实现了对应方法,比如Person类要存在getName()、getAge()、getLocation()三个无参方法,否则仍会抛出方法不存在异常
  • 动态执行外部文件传入的代码存在安全风险,禁止在生产环境执行来源不可信的语句,避免恶意代码注入
  • JDK15及以上版本移除了内置Nashorn引擎,使用方案2需要手动引入org.openjdk.nashorn:nashorn-core依赖

内容的提问来源于stack exchange,提问作者Brian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 20:06:26