在使用可选对象时,是否有一种有效的方法来执行向上转换。下面是一个示例代码:
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)?
发布于 2017-06-30 19:36:11
我会写一个这样的方法:
@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具有以下属性:它保证不会由于setter方法使用依赖于类型变量T的参数而引起的任何状态更改。呼。一口大口。我会做得更具体些。
因为Optional
T、SomeGenericType<T>等类型参数的方法)final (因此不能子类它以添加一个setter来违反前面的点)对于Optional<T>所持有的值(或缺少该值),您无法做任何事情来使它不再是T的一个实例(或缺少它)。
而且,由于T的每个实例也是其超类的实例,所以没有什么不安全的地方:
SuperclassOfT s = optionalOfT.get();因此,此方法是类型安全的(如果您在不存在的可选项上调用它,它将失败;但这不是类型错误)。
您将在ImmutableList.copyOf中找到类似的代码(上面将其称为"copyOf“的灵感所在,尽管它并不是真正的副本)。有一些setter方法(如add),但是这些方法会立即抛出UnsupportedOperationException,因此不会影响列表的状态。
请注意,虽然不可变类型具有上述所述的必要属性,以确保这样的强制转换安全,但类型不一定需要是不可变的,才能安全地执行强制转换。
例如,您可以有一个ErasableOptional<T>类型,它上有一个erase()方法,当被调用时,该方法将“当前”值转换为“缺失”值(即get()不再成功)。将这样一个实例强制转换到ErasableOptional<SupertypeOfT>是安全的,因为该值要么是T,要么是缺席;您不能使它不是SupertypeOfT的实例或缺席。
发布于 2017-07-01 06:54:57
可选的是,引用自java文档:
可能包含或不包含非空值的容器对象.其他依赖于是否存在包含的方法,如orElse() .
如我们所见,可选容器使用泛型类型来定义要包含的对象。
Optional <T>所以你可以这么做:
Optional<? extends A> a = func2(); // 2. Upcasting Will work :)并访问可选对象A类型的对象:
a.get();发布于 2017-06-30 19:14:30
您可以尝试使用映射函数:
Optional<A> oa = func2().map(v -> (A) v);请注意,您实际上不需要将(A)转换放在那里,但它使所发生的事情更加清晰。
https://stackoverflow.com/questions/44852936
复制相似问题