我在使用Optional
s和匿名类时遇到了一个奇怪的问题:
public class Foo {
interface Bar {
}
void doesNotCompile() {
Optional.of(new Bar() {
}).orElse(new Bar() {
});
}
void doesNotCompile2() {
final Bar bar = new Bar() {
};
Optional.of(new Bar() {
}).orElse(bar);
}
void compiles1() {
final Bar bar = new Bar() {
};
Optional.of(bar).orElse(new Bar() {
});
}
}
前两种方法不会编译并出现错误
java: incompatible types: <anonymous test.Foo.Bar> cannot be converted to <anonymous test.Foo.Bar>
我早就预料到了,因为两者都实现了接口Bar
这三种方法都有效。我也无法弄清楚为什么第三个选项可以解决问题。谁能解释一下?
可以使用类型见证来补充前两个类型:
Optional.<Bar>of(new Bar(){}).orElse(new Bar(){});
这允许编译器看到你期望返回Optional<Bar>
,然后 #orElse 可以推断接受任何Bar
您需要告诉可选,您需要为该接口提供一个栏。
Bar bar = new Bar();
Optional<Bar> o = Optional.of(new Bar() {}).orElse(bar);
案例compiles1
您的Optional
具有泛型类型Bar
,因为变量bar
的类型为Bar
。
您创建的类型Foo$1
的匿名类具有Bar
为超类型,因此该方法将进行编译。
案例doesNotCompile
在这里,Optional
具有泛型类型Foo$1
,并且您正在尝试将类型为Foo$2
的对象传递到没有Foo$1
作为超类型的orElse
对象中。因此编译错误。
案例doesNotCompile2
与doesNotCompile
类似,Optional
具有泛型类型Foo$1
,并且您正在尝试将bar
,一个类型为Bar
的变量传递到orElse
中,而该变量同样没有Foo$1
作为超类型。
避免这些错误
将类型见证添加到Optional::of
调用中。这会为您的Optional
提供泛型类型Bar
:
public class Foo {
interface Bar {
}
void doesNotCompile() {
Optional.<Bar>of(new Bar() {
}).orElse(new Bar() {
});
}
void doesNotCompile2() {
final Bar bar = new Bar() {
};
Optional.<Bar>of(new Bar() {
}).orElse(bar);
}
void compiles1() {
final Bar bar = new Bar() {
};
Optional.of(bar).orElse(new Bar() {
});
}
}