2016-02-17 87 views
1

擴展我的部門私有Libary我試圖實現一個isBetween方法。此方法是通用的,並且期望Comparable類型爲T的最小值,其最大值以及可變參數值。其目的是檢查是否所有值都在指定範圍內。指定方法參數的泛型類型

public static void main(String[] args) { 
    System.out.print(isBetween(1, 100, 200, 100, 1, 2)); 
    } 


    @SafeVarargs 
    public static <T extends Comparable> boolean isBetween(T minimum, T maximum, T... values) { 
    for (T value : values) { 
     if (!(value.compareTo(minimum) >= 0 && value.compareTo(maximum) <= 0)) 
     return false; 
    } 
    return true; 
    } 

這工作得很好。但是類型T可以包含任何Comparable對象。方法調用:

System.out.print(isBetween(1, 100, 200, 100, "How awkward", 2)); 

也將在編譯時被接受。 這根本不是類型安全的,不能被接受。

兩種解決方案進入了我的腦海:

1.呼叫像下面

System.out.print(Class.<Integer>isBetween(1, 100, 200, 100, 1, 2));

2.方法使U類型的我的方法的參數之一,擴展類型T至類型U

這兩個「解決方案」似乎都不是很優雅。第一個需要在調用方法之前編寫額外的代碼,第二個代碼看起來像是黑客。

有沒有更優雅的方法來解決我的問題?

+3

'>'? – fge

+0

偉大的這並沒有進入我的腦海,謝謝:) –

回答

3

那麼,這可以很容易地由avoiding raw types修復。

讓我們看看你的代碼:

public static <T extends Comparable> boolean isBetween(T minimum, T maximum, T... values) { 
    // ... 
} 

T是一個很好的和通用的,但Comparable是原始類型。你想Comparable<T>,讓你的方法應該是這樣的:

public static <T extends Comparable<T>> boolean isBetween(T minimum, T maximum, T... values) { 
    // ... 
} 

然後isBetween(1, 100, 200, 100, "How awkward", 2)將不再可能。


isBetween方法允許「相等」的參數類型,如果他們有它實現Comparable一個等於超類。

例如使用java.util.Datejava.sql.Date(用戶fge有這個好主意):

isBetween(new java.util.Date(1L), new java.util.Date(4L), new java.sql.Date(5L)) 

這將導致「假」,因爲第三個參數是「大」,比上界。並且java.sql.Date被接受,因爲它延伸java.util.Date並且將推斷爲T,它作爲「實現Comparable的共同父類」。

+1

然而,如果你的參數是'java.sql.Date's :) – fge

+1

@fge這將失敗如果參數是'java.util.Date'和'java .sql.Date',然後不,它也可以。這個方法允許有一個共同的超類的參數,它也實現了「可比較的」。 – Tom

+0

@fge或者我誤解了你的評論? – Tom

1

讓它<T extends Comparable<T>>

@SafeVarargs 
public static <T extends Comparable<T>> boolean isBetween(T minimum, T maximum, T... values) { 
    for (T value : values) { 
     if (!(value.compareTo(minimum) >= 0 && value.compareTo(maximum) <= 0)) 
      return false; 
    } 
    return true; 
} 

這將在編譯失敗。

0

使用可比較的< T>代替原始可比。這樣,你將確保類型T的所有實例都是相同的類型,並且在編譯時會失敗。

1

另一種方法可以做到這一點是在Comparator傳遞,而不需要TComparable

public static <T> boolean isBetween(Comparator<? super T> comparator, 
     T minimum, T maximum, T... values) { 
    for (T value : values) { 
     if (!(comparator.compare(value, minimum) >= 0 && 
       comparator.compare(value, maximum) <= 0)){ 
      return false; 
     } 
    } 
    return true; 
} 

這樣,但是你想你比較的對象,他們並不需要爲Comparable

你也可以提供類似的方法將其他的答案,跳過寫ComparatorTComparable

public static <T extends Comparable<? super T>> boolean isBetween(T minimum, 
     T maximum, T... values) { 
    return isBetween(T::compareTo, minimum, maximum, values); 
} 
+0

我喜歡用比較器的想法。這個想法是爲了簡單的目的做一個簡單的方法,但我也可以實現你的擴展方法:)...可悲的是我們使用java 7,我希望我們儘快收到更新 –

+0

java 8樣本不適用於我他無法解決方法 –

+0

@TomWellbrock我已經用eclipse和javac 1.8.0_51編譯它,這兩種方法每次都有效,但調用比較器版本給了我一個javac錯誤。您可能需要更改其中一種方法的名稱。你正在使用哪個編譯器版本? – Alex