确定表达式的结果类

时间:2015-03-02 22:46:24

标签: java reflection

是否有一种简单的方法来决定Java数学表达式的Java类?例如,我可以计算像String + double这样的结果类,但是有什么东西在运行时给出了混合类的任何有效表达式的结果类吗?

背景:我需要这个,因为我在运行时使用Java反射来调用带有参数的方法。参数已从文本解析为Expression对象,其中Expression是我处理表达式的类。表达式可以由其他表达式组成。因此,例如我可能正在解析代码:

double c = 2.2;
double d = 3.3;
long e = 4;
int f = 1000;
double a = 0;
double b = 0;
MyObject object = new MyObject();
object.getSomething(a, b, (c+d+e)/f);

我知道a和b的类,因为它们是定义的变量,但是在我可以执行以下操作之前需要计算第三个类的参数:

Method method = MyObject.class.getMethod("getSomething", double.class, double.class, ????);

3 个答案:

答案 0 :(得分:1)

首先,您无法了解ab,因为ab不是< EM>物体。它们是基元类型 double的局部变量。在java中,您有两种基本类型:基本类型(booleanbytecharshortintlong,{ {1}},float,可能还有double)和类类型。但是,还有一种称为 autoboxing (和 autounboxing )的机制,它可以在必要时在原始类型和相应的原始包装类之间自动转换&#34; (voidBooleanByteCharacterShortIntegerLongFloat) 。您可以使用此自动转换来确定表达式的类型。例如:

Double

注意事项:当混合原始类型和包装类的变量(和/或参数和/或返回值)时,很容易失去对类型的跟踪。特别是,Java反射API主要用于包装类,但主要用于包装类。这意味着,例如,方法byte a= 10 ; float b= 16.3 ; int c= 34 ; Object o= a * b + c ; o.getClass(); // Should be Double or one of the primitive wrapper classes in the general case // You can easily convert this to double.class through an if/elseif sequence // or a Map. 仅支持类类型的参数,并且由于自动装箱,Java会将任何基本类型转换为包装器对象,即使目标方法确实需要原语(在这种情况下会有原语)在反射调用之前的内部转换回原始类型)。作为一个很好的实验,如果您的编译器或IDE支持它,请尝试关闭自动装箱/取消装箱。如果不是这样,请将它们配置为在自动装箱/取消装箱时产生警告。

现在,如果您的数值以多态方式(如String,Object或类似方式)表示,那么您将需要为结果类型的操作定义自己的规则(或者在Java语言本身之后对它们进行建模)并相应地实施它们。这是因为Java自动装箱/拆箱是一种静态机制。

答案 1 :(得分:1)

我同意Mario Rossi's answer

此外,即使您使用的是引用表达式,也不能通常从示例调用的实际参数类型中推断出形式参数的类型。考虑一下这个程序:

import java.lang.reflect.Method;

class Test {
  public static void main(String[] args) throws NoSuchMethodException, SecurityException {
    double a = 3.0;
    new Test().myMethod(a);
    Method method = Test.class.getMethod("myMethod", Double.class);
    System.out.println(method);
  }

//  public void myMethod(Double d) {
//    System.out.println("Double version");
//  }

  public void myMethod(Number d){
    System.out.println("Number version");
  }
}

如上所述,它因NoSuchMethodException而失败,因为我正在寻找一个Double参数,而唯一的方法需要一个Number。如果我取消注释第一个myMethod声明,则getMethod调用会成功。

答案 2 :(得分:1)

这个答案基于这样一个假设,即目标接近完整的Java代码解释。

有关表达式类型的信息是直接或通过引用在Java语言规范Chapter 15. Expressions中提供的。需要实施的实际规则数量小于可能出现的规则数,因为许多表达式表单共享相同的转换规则。例如,正如在对该问题的评论中已经提到的那样,具有数字操作数的二元运算符(包括可以取消装箱为数字的操作数)通常使用binary numeric promotion

我看了一下,但没有成功,为了给定一个电话寻找合适的Method对象的捷径。您可能需要实际执行15.12. Method Invocation Expressions中描述的步骤。如果是这样,您可以使用getMethods方法而不是getMethod,并将规则应用于Method引用数组。