如何向上转换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 extends T> opt) { return (Optional ) opt; }
(如果您不喜欢名称copyOf
,请参阅下面关于Guava的ImmutableList
评论)
这在运行速度方面非常有效:演员在编译时被省略:
static java.util.Optional copyOf(java.util.Optional extends T>); Code: 0: aload_0 # Read the parameter. 1: areturn # Return the parameter.
所以唯一的代价就是方法调用; 这很容易被JIT消除。
然后你可以调用:
Optional a = copyOf(func2());
这是安全的,因为Optional
具有以下属性:保证不会由setter方法引起任何状态更改,这取决于类型变量T
参数。 唷。 相当满口。 我会让它更具体。
因为Optional
- 没有setter方法(任何类型,但更
SomeGenericType
是没有采用类型T
参数,SomeGenericType
等) - 是
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 extends A> a = func2(); // 2. Upcasting Will work :)
并为可选对象访问类型为A的对象:
a.get();