简体   繁体   English

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

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

At runtime, in my Java program, given a String, I 'd like to know the return type. 在运行时,在我的Java程序中,给定一个String,我想知道返回类型。 For example: 例如:

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

There is no need to actually evaluate the code: I just need the return type. 没有必要实际评估代码:我只需要返回类型。 How can I do this with the JDK runtime compiler, ECJ JDT or any other pure Java dependency? 如何使用JDK运行时编译器,ECJ JDT或任何其他纯Java依赖项执行此操作?


Detailed code: Here's a simplified, pseudo-code unit test for this code: 详细代码:以下是此代码的简化伪代码单元测试:

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"}));
    }
}

I think this depends on the range of input you want to be able to process. 我认为这取决于您希望能够处理的输入范围。

You see, in the end you are asking: how do I evaluate string expressions at runtime. 你看,最后你要问:我如何在运行时评估字符串表达式。

So, the short answer is: you need some kind of interpreter / REPL implementation; 所以,简短的回答是:你需要某种解释器/ REPL实现; or at least "parts" of that. 或至少“部分”。

Another approach could be to use the javax compiler to simply compile the thing, and then deduce the type, like here . 另一种方法可能是使用javax编译器简单地编译该东西,然后推断出类型,就像这里一样。

Other options would go along the lines of certain "compiler construction" topics, like constant folding . 其他选项将遵循某些“编译器构造”主题,如常量折叠

I've not tried this ... 我没试过这个......

  1. Wrap your expression in code like this: 用以下代码包装表达式:

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

  3. Parse the compilation error message to extract the compiler's idea of the RHS type. 解析编译错误消息以提取编译器对RHS类型的想法。

The problem is that an expression like Math.nextInt() might require an import to be compilable, and I doubt that there is a bombproof way to infer what the import ought to be. 问题是像Math.nextInt()这样的表达式可能需要导入才能编译,我怀疑是否有一种防弹方式来推断导入应该是什么。 Still, this should work for a useful subset of expressions. 不过,这应该适用于一个有用的表达式子集。

This approach is also fragile and non-portable since it depends on the precise form of the compilation error message which is liable to be compiler / version dependent. 这种方法也很脆弱且不可移植,因为它取决于编译错误消息的精确形式,这可能是编译器/版本依赖的。


A better solution (but more work) would be to implement a parser and type-checker for your Java subset expression language. 更好的解决方案(但更多工作)是为Java子集表达式语言实现解析器和类型检查器。

To do this for arbitrary expressions, you need a full Java front end that will parse the string and determine its type. 要为任意表达式执行此操作,您需要一个完整的Java前端,它将解析字符串并确定其类型。 In essence, you need what the compiler does. 实质上,您需要编译器所做的事情。

Eclipse JDT may offer a solution; Eclipse JDT可以提供解决方案; I'm not very familar with it. 我不是很熟悉它。

Our DMS Software Reengineering Toolkit with DMS's full Java front end can do this. 我们的DMS软件再造工具包与DMS的完整Java前端可以做到这一点。 DMS parses source according to the front end it is using, and then can call on front end services to analyze that code. DMS根据它正在使用的前端解析源,然后可以调用前端服务来分析该代码。

The Java front end provides parsing for Java in its various versions and various ways to parse (a file, a stream, a string), and will then build a tree for the parsed text. Java前端以各种版本和各种解析方式(文件,流,字符串)为Java提供解析,然后为解析的文本构建树。 The Java name resolver built into the front end can be asked to compute the type of an arbitrary expression according to the scoping rules in effect at a specific point in the code. 可以要求内置在前端的Java名称解析器根据代码中特定点有效的作用域规则计算任意表达式的类型。

For OP, this may not be what he wants since he insists on a Java-based answer and DMS is not Java-based (he did ask for "... any other dependency"). 对于OP,这可能不是他想要的,因为他坚持基于Java的答案而DMS不是基于Java的(他确实要求“......任何其他依赖”)。 The closest one might come here is invoke DMS as a sub-process, and ask DMS to print the type of the expression. 最接近的可能是调用DMS作为子进程,并要求DMS打印表达式的类型。 If his expressions have an extremely small number of types as shown in his example, this would probably work. 如果他的表达式具有极少数类型,如他的示例所示,这可能会起作用。 If not, he's going to need a complex bit of machinery to read expression types, which in their full glory (eg, package-resolved, templated form) can be pretty complex. 如果没有,他将需要一个复杂的机器来读取表达式类型,这些表达式的完整荣耀(例如,包解析,模板化形式)可能相当复杂。

If OP is willing to severely restrict the class of expressions he needs to handle to just simple arithmetic, he might be able to build his own expression parser and work out the type for himself. 如果OP愿意严格限制他需要处理的表达式类别只是简单的算术,他可能能够构建自己的表达式解析器并为自己计算出类型。 See my SO answer on how to build a recursive descent parser by hand: https://stackoverflow.com/a/2336769/120163 This same thread of answers also shows how to build a tree and 'evaluate' it; 请参阅我的SO答案,了解如何手动构建递归下降解析器: https//stackoverflow.com/a/2336769/120163这个相同的答案线程还展示了如何构建树并“评估”它; he can evaluate it for the type rather than the computed result. 他可以根据类型而不是计算结果来评估它。

Otherwise he is going to need the big hammer. 否则他将需要大锤子。

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

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