当前位置: 首页 > 面试题库 >

如何上载Java 8 Optional中包含的对象?

扈高逸
2023-03-14
问题内容

在使用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.)?


问题答案:

我会写一个像这样的方法:

@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具有以下属性:保证不会因使用依赖于type变量的参数的setter方法引起任何状态更改T。ew
满口。我会更具体一些。

因为 Optional

  1. 没有setter方法(任何种类的,但更一般的是没有采取类型的参数TSomeGenericType<T>等)
  2. final(因此您不能将其子类化以添加违反前一点的二传手)

您无法对Optional<T>(或缺乏)持有的价值做任何事情,使其 不会 成为T(或缺乏)的实例。

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

SuperclassOfT s = optionalOfT.get();

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

您将在Guava的ImmutableList.copyOf代码中找到类似的代码(上面的代码称为“
copyOf” 的灵感,即使它并不是真正的副本)。在那里,那里
setter方法(像add),但这些方法马上抛出UnsupportedOperationException秒,因此不会影响到列表的状态。

请注意,尽管不可变类型具有上述必需的属性才能使这种类型转换安全,但是,为了安全地执行类型转换,该类型不一定必须是不可变的。

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



 类似资料:
  • 问题内容: 如何Foo从Java访问包对象中包含的对象? 问题答案: 也许从Scala 2.8.1开始,这已经发生了变化,但是该提议不起作用。您必须使用。 对于对象,方法等,它有所不同。考虑到scala类: 您可以访问foo,bar而baz在Java中,如: 当我试图弄清楚这一点时,我以为我们遇到了麻烦,因为Scala生成了一个名为的类,当然您不能在Java中导入该类。幸运的是,我们只需要pack

  • 问题内容: 我正在尝试用Java创建一个简单的图像编辑程序。我制作了一个对象,其中包含有关正在编辑的图像的所有信息(一些基本属性,所应用的效果列表,层列表等),我想要一种简单的方法将其保存到磁盘,以便稍后再次打开。 我发现使用Java的defualt 接口可能正是我想要的,我可以将整个对象写到文件中,稍后再读回内存中。但是,包括和不能序列化(其他所有方法都可以)。 我知道可以重写和方法,但我从未这

  • 我有以下几门课: 我将序列化为json格式。对于json序列化,我使用Jackson。 现在,如果、和、分别为空,我想不要将和包含到json中。 正如我所强调的,我应该编写cistom串行化程序,但我不明白是为哪个实体编写的。还是?怎么做的? 附注。 本主题说明如何忽略容器中的空值。我的问题是如何忽略容器中只有空值的对象

  • 问题内容: 当编译我们的项目,我们创建几个档案(静态库),说和每个包含定义函数的对象文件和。然后,将这些归档文件合并到一个共享对象中,例如,这是我们的主要可分发目标之一。 例如,在示例程序中使用此共享库时,链接失败,因为未定义对函数和的引用。 但是,当我直接将最终的可执行文件与归档文件(静态库)链接时,它可以工作。 我的猜测是,归档中包含的目标文件未 链接 到共享库中,因为它们没有在共享库中使用。

  • 我正在使用和。 我正在努力获取子对象的子对象来填充。下面是我的课。 应用程序类; 子类: ChildRelationshipType类: 存储库中GetAll方法的一部分,以返回所有应用程序: 子类包含对ChildRelationshipType类的引用。要处理应用程序的子级,我需要这样做: 我在这里得到一个错误,即对象上下文已经关闭。 如何指定每个子对象必须包括对象,就像我上面所做的那样?