2015-03-02 84 views
0

是否有一種簡單的方法來決定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, ????); 
+0

爲什麼你不只是使用方法預期的類型?在任何情況下,結果都需要進行類型化。 – sujitv 2015-03-02 22:53:34

+0

c,d,e和f的類型是什麼? Java語言規範中提供了數字類型升級規則。 – 2015-03-02 22:58:29

+0

@sujitv可能有許多方法具有相同的名稱但參數不同。 – 2015-03-02 22:58:49

回答

1

排在首位,你可以不知道ab因爲ab沒有對象。它們是原始類型double的局部變量。在Java中,你有兩個基本種類型:基本類型(booleanbytecharshortintlongfloatdouble,也許void)和類類型。然而,也有稱爲自動裝箱(和autounboxing)機制,自動轉換時的原始類型和它們相應的「原始封裝類」之間必要的(BooleanByteCharacterShortIntegerLongFloatDouble )。您可以使用此自動轉換來確定表達式的類型。例如:

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反射API的工作主要是如果不是唯一的包裝類。這意味着,例如,該方法invoke僅支持類類型的參數,並且由於自動裝箱功能,即使目標方法真的期望原語,Java也會將任何原語類型轉換爲包裝對象(在這種情況下,將會有內部轉換返回到反射調用之前的原始類型)。作爲一個很好的實驗,如果您的編譯器或IDE支持它,請嘗試關閉自動裝箱/取消裝箱。如果沒有,請將它們配置爲在自動裝箱/拆箱時生成警告。現在,如果您的數值以多態方式表示(如字符串,對象或類似方式),那麼您將需要爲結果類型的操作定義自己的規則(或者在Java語言之後對其進行建模本身)並相應地實施。這是因爲Java自動裝箱/拆箱是一種靜態機制。

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,因爲我在尋找一個雙參數的唯一方法需要一個號碼。如果我取消註釋第一個myMethod聲明,則getMethod調用將成功。

1

此答案基於這樣的假設,即目標接近於完整的Java代碼解釋。

有關表達式類型的信息直接或通過引用提供給Java語言規範Chapter 15. Expressions。實際需要實施的規則數量比它看起來要少,因爲許多表達形式組共享相同的轉換規則。例如,正如在對該問題的評論中已經提到的那樣,具有數字操作數的二元運算符(包括可以取消裝箱到數字的操作數)通常使用binary numeric promotion

我已經查看了針對給定呼叫找到正確的Method對象的捷徑,但未成功。您可能需要實際完成15.12. Method Invocation Expressions中描述的步驟。如果是這樣,則可以使用getMethods方法而不是getMethod,並將規則應用於Method引用的數組。

+0

是的,你已經發現了我的祕密,我已經構建了一個Java解釋器在Java中,這是一種瘋狂的類型,它經常被嘲笑,但如果您希望基於Web的編碼可用於您的框架的用戶,例如看看SalesForce.com – 2015-03-03 01:56:30