3 回答

TA貢獻(xiàn)1786條經(jīng)驗(yàn) 獲得超13個(gè)贊
您可以Try.of()使用返回的顯式泛型類(lèi)型進(jìn)行調(diào)用以滿足編譯器檢查。就像是:
Try.<Seq<? extends Number>of(() -> List.of(1,2,3))
Try.of()返回類(lèi)型Try<T>其中T是供應(yīng)商返回的類(lèi)型。并且因?yàn)長(zhǎng)ist.of(T t...)return List<T>,那么編譯器看到的最終類(lèi)型是Try<List<Integer>,這不是方法返回的類(lèi)型定義的。具有特定類(lèi)型的 Java 泛型是不變的,它們不支持協(xié)變或逆變替換,因此List<Integer> != List<Number>.
工作示例:
import io.vavr.collection.List;
import io.vavr.collection.Seq;
import io.vavr.control.Try;
interface Lol {
default Try<Seq<? extends Number>> lol() {
return Try.of(List::empty);
}
}
class LolImpl implements Lol {
@Override
public Try<Seq<? extends Number>> lol() {
return Try
.<Seq<? extends Number>>of(() -> List.of(1, 2, 3))
.onFailure(t -> System.out.println(t.getMessage()));
}
public static void main(String[] args) {
System.out.println(new LolImpl().lol());
}
}
輸出:
Success(List(1, 2, 3))
通用示例類(lèi)型推斷問(wèn)題
進(jìn)一步調(diào)查表明,這很可能是一個(gè)通用的編譯器問(wèn)題??纯聪旅娴钠胀?Java 示例:
import java.util.Arrays;
import java.util.List;
import java.util.function.Supplier;
interface Some<T> {
static <T> Some<T> of(Supplier<T> supplier) {
return new SomeImpl<>(supplier.get());
}
default Some<T> shout() {
System.out.println(this);
return this;
}
class SomeImpl<T> implements Some<T> {
private final T value;
public SomeImpl(T value) {
this.value = value;
}
}
static void main(String[] args) {
final Some<List<CharSequence>> strings = Some.of(() -> Arrays.asList("a", "b", "c"));
}
}
此代碼編譯沒(méi)有任何問(wèn)題,編譯器Arrays.asList()從左側(cè)的預(yù)期類(lèi)型推斷返回的類(lèi)型:
現(xiàn)在,如果我調(diào)用這個(gè)Some<T>.shout()
方法,它什么都不做并返回Some<T>
,編譯器不是從預(yù)期的變量類(lèi)型,而是從最后返回的類(lèi)型推斷類(lèi)型:
當(dāng)然Arrays.asList("a","b","c")
returnsList<String>
和this is the type
shout()`方法推斷并返回:
指定顯式類(lèi)型Some<T>.of()
可以解決問(wèn)題,如Try.of()
示例所示:
我正在搜索有關(guān)類(lèi)型推斷的 Oracle 文檔,并且有以下解釋?zhuān)?/p>
Java 編譯器利用目標(biāo)類(lèi)型來(lái)推斷泛型方法調(diào)用的類(lèi)型參數(shù)。表達(dá)式的目標(biāo)類(lèi)型是 Java 編譯器期望的數(shù)據(jù)類(lèi)型,具體取決于表達(dá)式出現(xiàn)的位置。
來(lái)源:https : //docs.oracle.com/javase/tutorial/java/generics/genTypeInference.html#target_types
在這種情況下,看起來(lái)“取決于表達(dá)式出現(xiàn)的位置”意味著從先前返回的確切類(lèi)型推斷類(lèi)型。這將解釋為什么跳過(guò)shout()
方法使編譯器知道,我們期望Some<List<CharSequence>>
并且當(dāng)我們添加shout()
方法時(shí)它開(kāi)始返回Some<List<String>>
,因?yàn)檫@是shout()
方法從返回的Some.of()
方法類(lèi)型中看到的。希望能幫助到你。

TA貢獻(xiàn)1828條經(jīng)驗(yàn) 獲得超3個(gè)贊
您的問(wèn)題的答案與 Java 的類(lèi)型推斷以及類(lèi)型方差(在我們的示例中為協(xié)方差)有關(guān)。它與 Vavr 沒(méi)有任何關(guān)系。
Try<List<Integer>>是 的子類(lèi)型Try<? extends Seq<? extends Number>>。
但Try<List<Integer>>不是 的子類(lèi)型Try<Seq<? extends Number>>。
將lol()方法的返回類(lèi)型更改為T(mén)ry<? extends Seq<? extends Number>>,所有都將編譯正常。
讓我們來(lái)詳細(xì)看看。
public Try<Seq<? extends Number>> lol() { // line 1
return Try.of(() -> List.of(1, 2, 3)) // line 2
//.onFailure(Object::hashCode) // line 3
;
}
該lol()方法確實(shí)返回一個(gè)類(lèi)型的值Try<Seq<? extends Number>>(參見(jiàn)第 1 行)。
第 2 行中的 return 語(yǔ)句返回一個(gè)Try使用工廠方法構(gòu)造的實(shí)例Try.of(...)。在 Vavr 0.9.x 中,它是這樣定義的:
static <T> Try<T> of(CheckedFunction0<? extends T> supplier) {
// implementation omitted
}
編譯器推斷:
// type T = Seq<? extends Number>
Try.of(() -> List.of(1, 2, 3))
因?yàn)樗枰瑫r(shí)匹配方法的返回類(lèi)型lol()和CheckedFunction0工廠方法的簽名Try.of。
這編譯得很好,因?yàn)樵搒upplier函數(shù)返回一個(gè) type 值? extends T,即? extends Seq<? extends Number>,它與實(shí)際返回類(lèi)型兼容List<Integer>(參見(jiàn)上面的 TL;DR 部分)。
如果我們現(xiàn)在取消注釋.onFailure部分(第 3 行),那么T工廠方法的泛型類(lèi)型參數(shù)Try.of不再具有返回類(lèi)型的范圍lol()。編譯器推斷T為是,List<Integer>因?yàn)樗偸窃噲D找到適用的最具體的類(lèi)型。
.onFailure返回類(lèi)型的值,List<Integer>因?yàn)槿绻膶?shí)例返回完全相同的類(lèi)型。但Try<List<Integer>>不是Try<Seq<? extends Number>>(參見(jiàn)上面的 TL;DR 部分)的子類(lèi)型,因此代碼不再編譯。
使lol()方法在其返回類(lèi)型中協(xié)變將滿足編譯器:
// before: Try<Seq<? extends Number>>
Try<? extends Seq<? extends Number>> lol() { // line 1
return Try.of(() -> List.of(1, 2, 3)) // line 2
.onFailure(Object::hashCode); // line 3
}
順便說(shuō)一句,在 Vavr 的整個(gè)類(lèi)型層次結(jié)構(gòu)中定義正確的泛型變量,尤其是對(duì)于集合,是創(chuàng)建 Vavr 時(shí)的難點(diǎn)之一。Java 的類(lèi)型系統(tǒng)并不完善,還有一些東西是我們不能用 Java 的泛型來(lái)表達(dá)的。另請(qǐng)參閱我的博客文章“未來(lái) Java 中的聲明站點(diǎn)差異”
免責(zé)聲明:我是 Vavr(以前稱為 Javaslang)的創(chuàng)建者

TA貢獻(xiàn)1866條經(jīng)驗(yàn) 獲得超5個(gè)贊
似乎 Java 編譯器無(wú)法為您推斷出正確的類(lèi)型,在這種情況下,您需要提供繼續(xù)操作所需的其他類(lèi)型信息,例如:
class LolImpl implements Lol {
@Override
public Try<Seq<? extends Number>> lol() {
Try<Seq<? extends Number>> res = Try.of(() -> List.of(1, 2, 3));
return res.onFailure(Object::hashCode);
}
}
添加回答
舉報(bào)