Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何上传Java8中包含的对象?_Java_Oop_Design Patterns_Java 8_Optional - Fatal编程技术网

如何上传Java8中包含的对象?

如何上传Java8中包含的对象?,java,oop,design-patterns,java-8,optional,Java,Oop,Design Patterns,Java 8,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

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

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 ?
}
class A{}
类B扩展了{}
B func(){
//做点什么
返回新的B();
}
可选func2(){
//做点什么
返回可选的.of(新的B());
}
main(){
A=func();//向上投射效果很好
B=func();//向上投射效果很好
可选的b=func2();//1。工作正常
可选的a=func2();//2。如何使其工作?
}
(2.)给出了一个错误。我可以通过创建另一个函数来解决它


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

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

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

请注意,您实际上不需要将
(A)
强制转换放在那里,但它可以让您更清楚地了解正在发生的事情。

我将编写一个如下方法:

@SuppressWarnings("unchecked")  // Safe. See below.
static <T> Optional<T> copyOf(Optional<? extends T> opt) {
  return (Optional<T>) opt;
}
因此,唯一的成本是方法调用的成本;这很容易通过JIT消除

然后您可以像这样调用:

Optional<A> a = copyOf(func2());
因此,该方法是类型安全的(如果您在不存在的可选项上调用它,它将失败;但这不是类型错误)

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


请注意,尽管不可变类型具有上述必要的属性以确保此类强制转换的安全性,但该类型不一定必须是不可变的才能安全地执行强制转换


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

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

可能包含或不包含非空值的容器对象。。。。 取决于存在或不存在 包含,例如orElse()

正如我们看到的可选容器一样,使用泛型类型定义要包含的对象

Optional <T>

我认为最干净的方法是
Optional a=func2().flatMap(Optional::of)
Optional a=func2().map(Function.identity())
,因为两者都不需要强制转换,只使用现有功能。

这不是向上转换
Optional
在您的示例中不是
Optional
的超类型,这就是为什么这不是升级。仅供参考,这也是Scala选择支持声明站点差异而不是使用站点差异的原因之一。“高效”可能是
(可选。只需使用
Optional进行尝试为什么不使用
map
并在其中施放值,而不是施放可选值?我认为高效的OP意味着简单…@Federico,因为这将创建一个新实例。我不同意您对OP意图的评估(同时承认这是一种可能性;我们不应该事后猜测):当人们说“高效”时,有“最快”、“记忆最少”等的含义;他们会明确要求“简单”或“直接”如果简单是目标。重点。如果OP说高效,让我们坚持高效。很好的分析,顺便说一下。@Federico Peralta Schaffner:你不需要强制转换,只要
可选的a=func2().map(Function.identity());
将完成这项工作。但是Andy是对的,这将创建一个新对象,除非JVM对其进行优化。哪一个更有效,取决于实际度量。Java对lambda表达式使用
->
。此外,类型转换是不必要的。
可选oa=func2().map(v->v);
会起作用,用
Function.identity()替换
v->v
也会起作用。
SuperclassOfT s = optionalOfT.get();
Optional <T>
Optional<? extends A> a = func2(); // 2. Upcasting Will work :)
a.get();