使用Optional对象时是否有一种有效的方法来执行向上转换。 以下是示例代码:
class A{}
class B extends A{}
B func(){
//do something
return new B();
}
Optional<B> func2(){
//do something
return Optional.of(new B());
}
main() {
A a = func(); // Upcasting works fine
B b = func(); // Upcasting works fine
Optional<B> b = func2(); // 1. Works fine
Optional<A> a = func2(); // 2. How to make this work ?
}
(2。)给出错误。我可以通过创建另一个函数来解决它。
但是有没有一种有效的方法,所以func2()可以同时用于(1.)和(2.)?
答案 0 :(得分:7)
我会写一个这样的方法:
@SuppressWarnings("unchecked") // Safe. See below.
static <T> Optional<T> copyOf(Optional<? extends T> opt) {
return (Optional<T>) opt;
}
(如果您不喜欢名称copyOf
,请参阅我对以下番石榴ImmutableList
的评论
这在运行时速度方面非常有效:演员在编译时被省略:
static <T> java.util.Optional<T> copyOf(java.util.Optional<? extends T>);
Code:
0: aload_0 # Read the parameter.
1: areturn # Return the parameter.
所以唯一的代价就是方法调用;这很容易被JIT消除。
然后您可以调用:
Optional<A> a = copyOf(func2());
这是安全的,因为Optional
具有以下属性:保证不会因setter方法导致任何状态更改而取决于类型变量T
的参数。唷。相当满口。我会让它更具体。
因为Optional
T
,SomeGenericType<T>
等参数的方法final
(因此您不能将其子类化以添加设置者以违反前一点) Optional<T>
(或者没有)保持{em>不 T
的实例(或缺少)的值,你无法做任何事情
因为T
的每个实例也是其超类的一个实例,所以没有什么不安全的:
SuperclassOfT s = optionalOfT.get();
因此,此方法是类型安全的(如果您在非现有的可选项上调用它,它将失败;但这不是类型错误)。
你可以在Guava's ImmutableList.copyOf
中找到类似的代码(上面提到它的灵感来源&#34; copyOf
&#34;即使它不是真正的副本)。在那里,是 setter方法(如add
),但这些方法会立即抛出UnsupportedOperationException
,因此不会影响列表的状态。
请注意,虽然不可变类型具有上述必要属性以使这种类型转换安全,但类型不一定需要是不可变的来安全地执行转换。
例如,您可以使用ErasableOptional<T>
类型,其上有一个erase()
方法,在调用时,转换为&#34; present&#34;价值进入&#34;缺席&#34;价值(即get()
不再成功)。将此类实例强制转换为ErasableOptional<SupertypeOfT>
是安全的,因为该值为T
或不存在;你不能不 SupertypeOfT
或不存在的实例。
答案 1 :(得分:4)
您可以尝试使用映射功能:
var packageContents = {
'packages': [
{
'price': '23',
'name': 'Bronze Bundle Package',
'calendar': {
'type': '2year',
'color': 'Brushed Nickel',
},
'tpoint': {
'type': '',
'touches': '',
'years': '',
}
}
]
};
var bundleSet = null;
var bundleSet = null;
packageContents.packages.forEach(function (obj) {
for (var prop in obj) {
if (prop === 'calendar' || prop === 'tpoint') {
for (var subProp in obj[prop]) {
if (obj[prop][subProp] !== '') {
bundleSet = true;
} else {
bundleSet = false;
var notSelected = (obj.prop.subProp).val() !== '';
console.log(notSelected);
}
}
}
}
console.log(bundleSet);
});
请注意,您并非真的需要将Optional<A> oa = func2().map(v -> (A) v);
演员放在那里,但它会让您更清楚一些事情。
答案 2 :(得分:4)
可选,引自java doc:
一个容器对象,可能包含也可能不包含非null值.... 取决于是否存在的其他方法 包含,例如orElse()......
正如我们所见,可选容器,使用泛型类型来定义要包含的对象。
Optional <T>
所以你可以这样做:
Optional<? extends A> a = func2(); // 2. Upcasting Will work :)
并且为可选对象访问类型为A的对象:
a.get();
答案 3 :(得分:0)
我认为最干净的方法是fragment
或Optional<A> a = func2().flatMap(Optional::of)
,因为两者都不需要强制转换并且仅使用现有功能。