如何向上转换 Java 8 Optional 中包含的对象? [英] How to upcast object contained in Java 8 Optional?

查看:52
本文介绍了如何向上转换 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.

因为可选

  1. 没有 setter 方法(任何类型的,但更普遍的是没有采用 TSomeGenericType 等类型的参数)
  2. final(所以你不能子类化它来添加一个setter来违反上一点)
  1. has no setter methods (of any kind, but more generally none that take parameters of type T, SomeGenericType<T> etc)
  2. 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 UnsupportedOperationExceptions, 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆