2017-02-24 116 views
2

提供類型的變量值我有此類:對於另一個構造

public class Test<T> { 
    public Test() { 
     this(() -> true); // error here 
    } 

    public Test(Supplier<T> c) { 
    } 
} 

編譯失敗,此錯誤:

Error:(23, 24) java: incompatible types: bad return type in lambda expression 
    boolean cannot be converted to T 

唯一的解決方法,我發現使用靜態工廠方法:

public static Test<Boolean> makeDefault() { 
    return new Test<>(() -> true); 
} 

是否有任何方法可以讓構造函數不包含某些類型變量來調用另一個類型變量wh ich呢?爲什麼這個限制?

編輯: 我的用例:我有一個類可選keyExtractor。鍵類型是類型參數之一。如果用戶不提供keyExtractor,我只使用一個返回任何常量非空值。

+0

類型變量不屬於構造函數。它屬於類型(在實例上下文中)。 –

+0

編輯我的答案以修復術語。但爲什麼不編譯? – Oliv

+0

我發現了一個解決辦法:投將原始類型:'這((供應商)() - > TRUE);'。但爲什麼? – Oliv

回答

1

使其編譯,你可以做一個投給原始類型:

public class Test<T> { 
    public Test() { 
     this((Supplier)() -> true); 
    } 

    public Test(Supplier<T> c) { 
     this.c = c; 
    } 
} 

其缺點是,如果用戶在調用構造函數時提供了不正確類型的參數,他可能會得到意想不到的ClassCastException

Test<Integer> t = new Test<>(); 
System.out.println(t.supplier().get()); // prints "true" 

更好的辦法是使用靜態工廠方法,這將明確陳述Supplier類型用戶:

public class Test<T> { 
    public static Test<Boolean> newWithConstantSupplier() { 
     return new Test<>(() -> true); 
    } 

    public Test(Supplier<T> c) { 
     this.c = c; 
    } 
} 

在我的情況,我結束了去除T參數,並採取Supplier<?>,因爲我有在公共API沒有方法,暴露了T型,所以沒有點,爲用戶把它擺在首位:

public class Test { 
    public Test() { 
     this((Supplier)() -> true); 
    } 

    public Test(Supplier<?> c) { 
     this.c = c; 
    } 
} 
3

假設你寫:

Test<String> t = new Test<>(); 

導致其他構造函數被調用;有效:

Test<String> t = new Test<String>(() -> true); 

但這不是鍵入正確的:() -> true不提供String,它提供了一個Boolean(或Serializable,或Object)。

如果你想提供一個默認的構造函數這樣, 你需要返回,可強制轉換爲任何一個值:僅此值是null

this(() -> null); 

或者,刪除默認的構造函數,並提供一個不帶參數的工廠方法:

static Test<Boolean> createInstance() { 
    return new Test<>(() -> true); 
} 
相關問題