2014-03-13 80 views
0

這裏是我的一羣學生提出的問題的意譯,而且事實證明,找到一個答案是有點麻煩(對我來說,反正)比我預期:測試方法是否返回雙打

假設您要求我編寫一個具有String參數的方法f,並返回一個double。你現在希望通過編寫你自己的測試代碼來測試我是否已經正確地完成了自己的工作,如果我已經按照指定編寫了f,那麼這些代碼將會被編譯,但是如果我沒有編寫則不會編譯。

有些學生提出的這個不正確的解決方案:

System.out.println(f("cat")); 

這不是一個很好的測試,因爲它並不測試方法的返回類型。也就是說,即使我寫了f來返回一個String或一個int或一個布爾值,它也會被編譯,等等。

我提出的這個解決方案給學生:

double d = f("cat"); 

我的理由是,這個測試F是否接受字符串並返回雙打。但是,真的,這也不好。 f可以返回一個int(或任何「較窄」的原始數據類型),並且結果可以存儲在d中。

所以,我正在尋找的想法,一個簡單的解決(代碼一行或兩行,也許?)的問題:寫代碼如果f已被正確定義(字符串參數,將編譯,雙倍返還),但如果f沒有按照指定寫入,則不會編譯。

+0

[反思](http://docs.oracle.com/javase/tutorial/reflect/)。 – Maroun

+0

我意識到Java的反射存在,但沒有使用它。我不知道它滿足擺在問題中的「編譯時測試」部分,但我確實知道Reflection有很多開銷。有沒有非反射解決方案? – normKrumpe

回答

4

反思是最適合在這裏一般(這是一個非常不尋常的要求),但別的東西,至少會的工作是使用重載決議:提供可供選擇的方法與floatlongDouble參數,但void返回類型...和一個帶有參數類型爲double的方法和一個非void返回類型。然後檢查是否可以爲調用該方法的結果分配一個值,結果爲f。例如:

public void foo(long x) {} 
public void foo(float x) {} 
public void foo(Double x) {} 
public void foo(Object x) {} 
public int foo(double x) { 
    return 0; 
} 

// This will only compile if f is declared to return double 
int check = foo(f("cat")); 
+0

天才解決方案。 – Maroun

+0

不應該'檢查'是'雙'嗎? (雖然編譯器無關緊要) – Maroun

+0

@MarounMaroun:不是 - 它與'foo'返回的類型是相同的返回類型,它與'f'返回的類型完全不同。重要的是這是一個非虛無的方法......這就是我們真正關心的。 –

0

使用反射:獲得類java.lang.reflect.Method中,與名F和參數類型的字符串相匹配的實例,該實例的使用返回類型等於雙。TYPE

從Double類類文檔:

公共靜態final類TYPE表示基本類型雙

1

這裏的Class實例是一個編譯時斷言(雖然會產生假積極DoubleObject):

List<Double> a = new ArrayList<Double>(); 
a.add(f("cat")); 

或者乾脆:

double[] a = {f("cat")}; 

這裏是一個運行時斷言(雖然會產生假陽性DoubleFloatfloat):

try 
{ 
    double d = f("cat")/0; 
} 
catch (Exception e) 
{ 
    return false; 
} 
return true; 
+0

對於您的第一個解決方案,我喜歡它,並且它暗示ArrayList是不必要的...只是嘗試將返回存儲在Double中。但是,如果f被誤寫爲返回Double而不是double,那該怎麼辦? – normKrumpe

+0

@normKrumpe,正如我所說:「它會產生'雙重'的誤報*。 –

0

我們可以返回的對象類型,而不是和禁用的編譯器選項自動裝箱的IDE錯誤以獲得確切的返回類型以及.exc:int不能返回整數..等等

對於原語,我們需要反射,這可能是一個有點沉重的操作。