如何向上转换Java 8可选对象?

是否有一种有效的方法在使用Optional对象时执行向上转换。 这是一个示例代码:

class A{} class B extends A{} B func(){ //do something return new B(); } Optional func2(){ //do something return Optional.of(new B()); } main() { A a = func(); // Upcasting works fine B b = func(); // Upcasting works fine Optional b = func2(); // 1. Upcasting works fine Optional a = func2(); // 2. Upcasting would not work } 

(2.)给出错误。 我可以通过创建另一个函数来解决它。

但是有没有一种有效的方法,所以func2()可以用于(1.)和(2.)?

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

 @SuppressWarnings("unchecked") // Safe. See below. static  Optional copyOf(Optional opt) { return (Optional) opt; } 

(如果您不喜欢名称copyOf ,请参阅下面关于Guava的ImmutableList评论)

这在运行速度方面非常有效:演员在编译时被省略:

 static  java.util.Optional copyOf(java.util.Optional); Code: 0: aload_0 # Read the parameter. 1: areturn # Return the parameter. 

所以唯一的代价就是方法调用; 这很容易被JIT消除。

然后你可以调用:

 Optional a = copyOf(func2()); 

这是安全的,因为Optional具有以下属性:保证不会由setter方法引起任何状态更改,这取决于类型变量T参数。 唷。 相当满口。 我会让它更具体。

因为Optional

  1. 没有setter方法(任何类型,但更SomeGenericType是没有采用类型T参数, SomeGenericType等)
  2. final (所以你不能将它子类化为添加一个setter来违反前一点)

没有什么可以对Optional (或缺少)所持有的值做任何使它不是 T (或缺少T )的实例。

并且因为T每个实例也是其超类的一个实例,所以没有什么不安全的:

 SuperclassOfT s = optionalOfT.get(); 

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

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


请注意,虽然不可变类型具有上述必要的属性以使这种转换安全,但类型不一定需要是不可变的来安全地执行转换。

例如,你可以有一个ErasableOptional类型,它有一个erase()方法,当被调用时,将“当前”值转换为“缺席”值(即get()不再成功)。 将此类实例ErasableOptional转换为ErasableOptional是安全的,因为该值为T或不存在; 你不能使它不是 SupertypeOfT的实例或缺席。

可选的是,引自java doc:

一个容器对象,可能包含也可能不包含非null值….依赖于包含的是否存在的其他方法,例如orElse()……

我们可以看到Optional容器,使用generics类型来定义要包含的对象。

 Optional  

所以你可以这样做:

 Optional a = func2(); // 2. Upcasting Will work :) 

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

 a.get(); 

您可以尝试使用映射function:

 Optional oa = func2().map(v -> (A) v); 

请注意,您并不需要将(A)投射放在那里,但它会使发生的事情变得更加清晰。