繁体   English   中英

在运行时确定String中Java表达式的返回类型

[英]Determine return type of a Java expression in a String at runtime

在运行时,在我的Java程序中,给定一个String,我想知道返回类型。 例如:

  • 1 + 1返回int
  • 1L + 1L返回long
  • 1L + 1返回多long
  • 1 + 1.5返回double
  • 1 + 2 - 3 * 4 / 5 4/5返回int
  • 1 / 0返回int
  • 1 + Math.nextInt()返回int
  • 1.5 + Math.nextInt()返回double
  • Color.RED返回java.awt.Color
  • 假设a是int: a + 1返回int
  • 假设a是一个int: a + 1.5返回double

没有必要实际评估代码:我只需要返回类型。 如何使用JDK运行时编译器,ECJ JDT或任何其他纯Java依赖项执行此操作?


详细代码:以下是此代码的简化伪代码单元测试:

public static void ExpressionTyper {
    public String determineType(String expression, Map<String, String> variableTypes) {
       ... // How do I implement this?
    }
}
public void ExpressionTyperTest {
    @Test public void determineType() {
        assertEquals("int", ExpressionTyper.determineType("1 + 1", emptyMap());
        assertEquals("long", ExpressionTyper.determineType("1 + 1L", emptyMap());
        assertEquals("double", ExpressionTyper.determineType("1 + 1.5", emptyMap());
        assertEquals("int", ExpressionTyper.determineType("a + 1", mapOf({"a", "int"}));
        assertEquals("int", ExpressionTyper.determineType("a + b", mapOf({"a", "int"}, {"b", "int"}));
        assertEquals("double", ExpressionTyper.determineType("a + b", mapOf({"a", "double"}, {"b", "int"}));
    }
}

我认为这取决于您希望能够处理的输入范围。

你看,最后你要问:我如何在运行时评估字符串表达式。

所以,简短的回答是:你需要某种解释器/ REPL实现; 或至少“部分”。

另一种方法可能是使用javax编译器简单地编译该东西,然后推断出类型,就像这里一样。

其他选项将遵循某些“编译器构造”主题,如常量折叠

我没试过这个......

  1. 用以下代码包装表达式:

      public class Test { private Test xxx = <<insert expression>>; } 
  2. 编译代码。

  3. 解析编译错误消息以提取编译器对RHS类型的想法。

问题是像Math.nextInt()这样的表达式可能需要导入才能编译,我怀疑是否有一种防弹方式来推断导入应该是什么。 不过,这应该适用于一个有用的表达式子集。

这种方法也很脆弱且不可移植,因为它取决于编译错误消息的精确形式,这可能是编译器/版本依赖的。


更好的解决方案(但更多工作)是为Java子集表达式语言实现解析器和类型检查器。

要为任意表达式执行此操作,您需要一个完整的Java前端,它将解析字符串并确定其类型。 实质上,您需要编译器所做的事情。

Eclipse JDT可以提供解决方案; 我不是很熟悉它。

我们的DMS软件再造工具包与DMS的完整Java前端可以做到这一点。 DMS根据它正在使用的前端解析源,然后可以调用前端服务来分析该代码。

Java前端以各种版本和各种解析方式(文件,流,字符串)为Java提供解析,然后为解析的文本构建树。 可以要求内置在前端的Java名称解析器根据代码中特定点有效的作用域规则计算任意表达式的类型。

对于OP,这可能不是他想要的,因为他坚持基于Java的答案而DMS不是基于Java的(他确实要求“......任何其他依赖”)。 最接近的可能是调用DMS作为子进程,并要求DMS打印表达式的类型。 如果他的表达式具有极少数类型,如他的示例所示,这可能会起作用。 如果没有,他将需要一个复杂的机器来读取表达式类型,这些表达式的完整荣耀(例如,包解析,模板化形式)可能相当复杂。

如果OP愿意严格限制他需要处理的表达式类别只是简单的算术,他可能能够构建自己的表达式解析器并为自己计算出类型。 请参阅我的SO答案,了解如何手动构建递归下降解析器: https//stackoverflow.com/a/2336769/120163这个相同的答案线程还展示了如何构建树并“评估”它; 他可以根据类型而不是计算结果来评估它。

否则他将需要大锤子。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM