如何上载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
,请在下面查看我对番石榴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
具有以下属性:保证不会因使用依赖于类型变量T
的参数的setter方法导致任何状态更改. ew满口.我会更具体一点.
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.
因为Optional
- 没有设置方法(任何类型,但更普遍的是没有采用
T
,SomeGenericType<T>
等类型的参数) - 是
final
(因此您不能将其子类化以添加违反前一点的二传手)
- 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).
您会在番石榴的ImmutableList.copyOf
(上面的称呼为"copyOf
"的灵感,即使它并不是真正的副本).那里有 设置方法(如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<T>
类型,该类型上具有erase()
方法,该方法在被调用时将当前"值转换为缺少"值(即get()
不再成功) .将这样的实例强制转换为ErasableOptional<SupertypeOfT>
是安全的,因为该值要么是T
,要么是不存在.您不能使其 not 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屋!