首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何向上转换Java 8中包含的对象(可选)?

如何向上转换Java 8中包含的对象(可选)?
EN

Stack Overflow用户
提问于 2017-06-30 18:38:33
回答 4查看 13.4K关注 0票数 11

在使用可选对象时,是否有一种有效的方法来执行向上转换。下面是一个示例代码:

代码语言:javascript
复制
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)?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2017-06-30 19:36:11

我会写一个这样的方法:

代码语言:javascript
复制
@SuppressWarnings("unchecked")  // Safe. See below.
static <T> Optional<T> copyOf(Optional<? extends T> opt) {
  return (Optional<T>) opt;
}

(如果你不喜欢copyOf这个名字,请看下面我对番石榴的ImmutableList的评论)

就运行时速度而言,这是非常有效的:强制转换在编译时被省略:

代码语言:javascript
复制
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取消。

然后,您可以调用如下:

代码语言:javascript
复制
Optional<A> a = copyOf(func2());

这是安全的,因为Optional具有以下属性:它保证不会由于setter方法使用依赖于类型变量T的参数而引起的任何状态更改。呼。一口大口。我会做得更具体些。

因为Optional

  1. 没有setter方法(任何类型的方法,但更普遍地说,没有接受TSomeGenericType<T>等类型参数的方法)
  2. final (因此不能子类它以添加一个setter来违反前面的点)

对于Optional<T>所持有的值(或缺少该值),您无法做任何事情来使它不再是T的一个实例(或缺少它)。

而且,由于T的每个实例也是其超类的实例,所以没有什么不安全的地方:

代码语言:javascript
复制
SuperclassOfT s = optionalOfT.get();

因此,此方法是类型安全的(如果您在不存在的可选项上调用它,它将失败;但这不是类型错误)。

您将在ImmutableList.copyOf中找到类似的代码(上面将其称为"copyOf“的灵感所在,尽管它并不是真正的副本)。有一些setter方法(如add),但是这些方法会立即抛出UnsupportedOperationException,因此不会影响列表的状态。

请注意,虽然不可变类型具有上述所述的必要属性,以确保这样的强制转换安全,但类型不一定需要是不可变的,才能安全地执行强制转换。

例如,您可以有一个ErasableOptional<T>类型,它上有一个erase()方法,当被调用时,该方法将“当前”值转换为“缺失”值(即get()不再成功)。将这样一个实例强制转换到ErasableOptional<SupertypeOfT>是安全的,因为该值要么是T,要么是缺席;您不能使它不是SupertypeOfT的实例或缺席。

票数 8
EN

Stack Overflow用户

发布于 2017-07-01 06:54:57

可选的是,引用自java文档:

可能包含或不包含非空值的容器对象.其他依赖于是否存在包含的方法,如orElse() .

如我们所见,可选容器使用泛型类型来定义要包含的对象。

代码语言:javascript
复制
Optional <T>

所以你可以这么做:

代码语言:javascript
复制
Optional<? extends A> a = func2(); // 2. Upcasting Will work :)

并访问可选对象A类型的对象:

代码语言:javascript
复制
a.get();
票数 7
EN

Stack Overflow用户

发布于 2017-06-30 19:14:30

您可以尝试使用映射函数:

代码语言:javascript
复制
Optional<A> oa = func2().map(v -> (A) v);

请注意,您实际上不需要将(A)转换放在那里,但它使所发生的事情更加清晰。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44852936

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档