[英]Why can't I use wildcard with methods receiving a parameterized argument?
例如,我使用Measure.doubleValue(Unit<?> unit)
方法,該方法返回以指定Unit
表示的度量的double
Measure.doubleValue(Unit<?> unit)
值。 如果我將Unit<?>
變量傳遞給它,則會收到仍然非常隱秘的錯誤消息:
The method doubleValue(Unit<capture#27-of ?>) in the type Measurable<capture#27-of ?> is not applicable for the arguments (Unit<capture#28-of ?>)
如果有人可以解釋#27-of ?
內容,我將不勝感激#27-of ?
(或任何其他數字)的意思,並且是否有一種優雅的方法可以消除這種情況。 到目前為止,我刪除了<?>
並設置了調用方法@SuppressWarnings("unchecked")
(因此我傳遞了一個未經檢查的Unit
而不是Unit<?>
),並且一切都按預期進行,但是我對此感到很好奇,我覺得抑制警告不是一個好習慣(不是有點像空的捕獲塊嗎?)。
謝謝!
編輯:添加一些代碼。
(很抱歉,這很長,但是詳細說明了我遇到的問題。)
所以...如果我寫這個(非常愚蠢的例子):
Measure measure = Measure.valueOf("3 m");
measure = Measure.valueOf(measure.doubleValue(Unit.valueOf("km")), Unit.valueOf("km"));
System.out.println(measure);
它可以工作並打印“ 0.0030 km”。 但我得到警告“ 措施是一個原始類型引用泛型類型測量<Q>應進行參數設置。”在第一Measure
發生和警告“ 類型安全:該方法的doubleValue(單位)所屬的原始類型可測量引用通用。類型Measurable <Q>應該在 “ measure.doubleValue(Unit.valueOf("km"))
”上進行參數化 。
看到這些警告,我想我可以這樣調整(僅第一行):
Measure<Length> measure = Measure.valueOf("3 m");
然后我在分配的右側收到錯誤消息“ 類型不匹配:無法從Measure <capture#1-of?>轉換為Measure <Length> ”。 它(Eclipse)為我提供了將正確的部分轉換為(Measure<Length>)
。 但是然后我在右側部分收到警告消息“ 類型安全:未經檢查的從Measure <capture#1-of轉換為Measure <Length> ”。 建議修復: @SuppressWarnings
,我希望避免使用(我想是出於偏執的原因)。
因此,我返回到Measure measure = Measure.valueOf("3 m");
並嘗試將通配符賦予Measure
,顯然,此刻不知道“ 3 m”是什么意思。 它可以是Length
,也可以是Mass
或Time
。 所以我得到:
Measure<?> measure = Measure.valueOf("3 m");
在這條線上沒有警告或錯誤; 太棒了。 但是,在第二行:
measure = Measure.valueOf(measure.doubleValue(Unit.valueOf("km")), Unit.valueOf("km"));
我收到doubleValue
錯誤消息:“ 類型為Measurable <capture#3-of的方法doubleValue(Unit <capture#3-of?>)不適用於參數(Unit <capture#4-of? >) “。 建議將Unit.valueOf("km")
為(Unit<?>)
。 精細。 現在,我在完全相同的位置收到錯誤消息:“ 類型為Measurable <capture#3-of?>的方法doubleValue(Unit <capture#3-of?>)不適用於參數(Unit <capture#5 -of?>) ”。 請注意,數字已更改,因此這不是完全相同的參數,而是相似的原因。 然后,它執行完全相同的建議,因為它已經完成了,因此不會導致代碼中的任何更改。
這就是困擾我的原因。 使它工作的唯一方法似乎是@SuppressWarnings
或忽略它們。 奇怪嗎?
度量值類看起來像這樣嗎?
class Measure<T> {
double doubleValue(Unit<T> unit) {
...
}
}
在這種情況下,引用類型為Measure<?>
並不意味着您可以將任何類型的Unit
傳遞給doubleValue
方法。 相反,這意味着Measure
實例具有未知的泛型類型,並且將Unit
傳遞給其doubleValue
方法並不安全,因為編譯器無法確保類型兼容。
通配符並不意味着“任何類型”; 它的意思是“未知類型”。
更新:
valueOf(CharSequence)
返回未知類型的Measure
Measure<?>
。 要將其安全地轉換為所需的Measure
類型,必須使用Measure.asType()
方法。 與由Unit.valueOf(CharSequence)
方法創建的目標Unit
Unit.valueOf(CharSequence)
。
Measure<?> unknownMeasure = valueOf("3 m");
Unit<?> unknownUnit = Unit.valueOf("km");
Measure<Length> length = unknownMeasure.asType(Length.class);
Unit<Length> kilometer = unknownUnit.asType(Length.class);
length.doubleValue(kilometer);
查看Measure
類文檔中的示例。 它們將提供一些額外的深度。
Java泛型中的通配符表示“未知類型”。 在這里,將doubleValue()
方法定義為接受Unit<something1>
,其中方法未指定something1
。 然后,您將一些未知的something2
的值傳遞給調用方,它稱為Unit<something2>
。 編譯器錯誤消息表示沒有任何東西可以保證something1
和something2
指定相同的內容。
嘗試這個:
<T> double doubleValue(Unit<T> unit)
{
...
}
這意味着doubleValue()
不在乎 T
是什么。
為了擴展其他(出色的)答案,但是要具體一些JSR-275(我現在正在將其用於項目)。
這一點很有趣
建議修復:@SuppressWarnings,我希望避免使用(我想是出於偏執的原因)。
您是對偏執的想法是正確的,但是請考慮一下:您要告訴Measure
類解析任意String
,並返回任何類型的Measure
。 顯然,在這種情況下,您可能會或可能不會獲得Measure<Length>
(可能會傳遞“ 3 kg”),因此,留給庫的唯一選擇是返回Measure<?>
。 如果您想要一個Measure<Length>
,那么您必須以某種方式將其強制為-可能無法保證在編譯時是安全的。
在這種情況下,我認為@SuppressWarnings是完全可以接受的, 假設您知道字符串將始終是有效長度。 如果不是這樣,您將不可避免的ClassCastException
推遲到以后,這很糟糕。
但是 ,更好的(呼啦!)JSR-275確實為您提供了解決方法,將錯誤處理推到了正確的位置(在獲得Measure
,而不是在使用它后的某個時候)。 嘗試
Measure<Length> = Measure.valueOf("3 m").asType(Length.class);
asType
返回相應的Measure
通用類型,或者如果解析的單元的尺寸不是length,則失敗,但異常-這幾乎可以肯定是您想要的,對吧?
我認為這可以解決您的問題。
我無法重現您的問題,即以下代碼可以正常編譯(至少使用eclipse):
static double doubleValue(Unit<?> unit) {
return 0;
}
static void bla(Unit<?> u) {
doubleValue(u);
}
public static void main(String[] args) {
doubleValue(new Unit<String>());
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.