如何向上转换 Java 8 Optional 中包含的对象? [英] How to upcast object contained in Java 8 Optional?
问题描述
是否有一种在使用 Optional 对象时执行向上转换的有效方法.这是一个示例代码:
Is there an efficient way to perform upcasting while using an Optional object. Here is a sample code:
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.) 给出错误.我可以通过创建另一个函数来解决它.
(2.) gives an error. I can solve it by creating another function.
但是有没有一种有效的方法,使 func2() 可以同时用于 (1.) 和 (2.) ?
But is there an efficient way, so that func2() can be used for both (1.) and (2.) ?
推荐答案
我会写一个这样的方法:
I would write a method like this:
@SuppressWarnings("unchecked") // Safe. See below.
static <T> Optional<T> copyOf(Optional<? extends T> opt) {
return (Optional<T>) opt;
}
(如果你不喜欢copyOf
这个名字,请看我下面关于Guava的ImmutableList
的评论)
(If you don't like the name copyOf
, see my comment about Guava's ImmutableList
below)
这在运行速度方面非常有效:在编译时忽略了强制转换:
This is very efficient in terms of runtime speed: the cast gets elided at compile time:
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 消除.
so the only cost is that of a method call; this is easily done away with by the JIT.
然后你可以像这样调用:
You can then invoke like:
Optional<A> a = copyOf(func2());
<小时>
这是安全的,因为 Optional
具有以下属性:保证不会因 setter 方法采用依赖于类型变量 T
的参数而导致任何状态更改.呼.好一口.我会说得更具体.
This is safe because Optional
has the following property: it is guaranteed not to have any state changes caused by setter methods taking parameters dependent upon the type variable T
. Phew. Quite a mouthful. I'll make it more concrete.
因为可选
- 没有 setter 方法(任何类型的,但更普遍的是没有采用
T
、SomeGenericType
等类型的参数) - 是
final
(所以你不能子类化它来添加一个setter来违反上一点)
- has no setter methods (of any kind, but more generally none that take parameters of type
T
,SomeGenericType<T>
etc) - is
final
(so you can't subclass it to add a setter to violate the previous point)
您无法对 Optional<T>
(或缺少它)所持有的值做任何事情,使其不是T 的实例
(或缺少代码).
there is nothing you can do to the value held by the Optional<T>
(or lack thereof) that will make it not an instance of T
(or lack thereof).
而且因为 T
的每个实例也是它的超类的一个实例,所以没有什么不安全的:
And because every instance of T
is also an instance of its superclasses, there is nothing unsafe about:
SuperclassOfT s = optionalOfT.get();
因此,这个方法是类型安全的(如果你在一个不存在的可选项上调用它会失败;但这不是类型错误).
As such, this method is type safe (it will fail if you've invoked it on a non-present optional; but that's not a type error).
您会在 Guava 的 ImmutableList.copyOf
(上面称之为copyOf
"的灵感,即使它不是真正的副本).那里有 setter 方法(如add
),但这些方法会立即抛出UnsupportedOperationException
,因此不会影响列表的状态.
You will find similar code in Guava's ImmutableList.copyOf
(the inspiration for calling it "copyOf
" above, even though it's not really a copy). There, there are setter methods (like add
), but those methods immediately throw UnsupportedOperationException
s, and thus do not affect the list's state.
请注意,虽然不可变类型具有上述必要的属性以使此类转换安全,但该类型不一定需要不可变才能安全地执行转换.
Note that whilst immutable types have the necessary properties described above to make such a cast safe, the type does not necessarily need to be immutable to perform the cast safely.
例如,你可以有一个 ErasableOptional
类型,它有一个 erase()
方法,当调用时,它转换了一个当前"值转换为缺失"值(即 get()
不再成功).将这样的实例转换为 ErasableOptional
是安全的,因为该值要么是 T
,要么不存在;你不能让它不是SupertypeOfT
的实例或不存在.
For example, you could have an ErasableOptional<T>
type, which has an erase()
method on it which, when called, converted a "present" value into an "absent" value (i.e. get()
no longer succeeds). It would be safe to cast such an instance to an ErasableOptional<SupertypeOfT>
because the value is either a T
or absent; you can't make it not an instance of SupertypeOfT
or absent.
这篇关于如何向上转换 Java 8 Optional 中包含的对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!