为什么Java堆栈选项不可用?
我通常对Java语言的设计非常满意,但今天我遇到了一个奇怪的设计选择。 我不知道有哪个平台可以建议对9或10版的Java语言进行更改,因此我在这里写这篇文章为什么Java堆栈选项不可用?,java,optional,language-design,Java,Optional,Language Design,我通常对Java语言的设计非常满意,但今天我遇到了一个奇怪的设计选择。 我不知道有哪个平台可以建议对9或10版的Java语言进行更改,因此我在这里写这篇文章 使用Optionals,如果值为null,您可以更好地控制行为 今天,我将流中的一个值映射到一个可选的。 我真的很惊讶,findFirst然后给了我一个Optional,而不仅仅是Optional 选择选项的意义何在? Optional<Optional<T>> => Optional<T> Op
使用Optionals,如果值为
null
,您可以更好地控制行为
今天,我将流中的一个值映射到一个可选的
。
我真的很惊讶,findFirst
然后给了我一个Optional
,而不仅仅是Optional
选择选项的意义何在?
Optional<Optional<T>> => Optional<T>
Optional.of(Optional.of("")) => Optional.of("")
对于Java9和Streams,这可以通过.flatMap(可选::stream)
解决,但这只是一个解决方法和样板代码
如果Optionals通常不会堆叠并且总是平铺,不是更好吗?
Optional<Optional<T>> => Optional<T>
Optional.of(Optional.of("")) => Optional.of("")
此外,如果您正在使用optionals,您只对对象感兴趣。因此,如果您试图获取对象,则始终必须双重获取并检查可选项
if(optionalOfOptional.isPresent()) {
optional = optionalOfOptional.get();
if(optional.isPresent()) {
objectOfInterest = optional.get();
}
}
我甚至认为这是一个错误的来源,因为如果你的对象存在,你总是需要检查两个选项
if(optionalOfOptional.isPresent() && optionalOfOptional.get().isPresent()) {
...
}
只有检查第一个可选项,才容易导致错误
另外,为什么一开始就有一个可选的null
?是否可以选择不使用null
在方法层面上,这是肯定可以解决的 例如,
Optional.of
可能看起来像:
public static <T> Optional<T> of(T value) {
return value instanceof Optional ? value : new Optional<>(value);
}
公共静态可选值(T值){
返回值instanceof Optional?值:新建可选(值);
}
在类型级别上,这可能没有那么容易。我在其他地方谈到了这一点,它违反了
Optional
的承诺:摆脱NullPointerException
s
因此,我认为在可选API中允许
可选
是有缺陷的设计。如果给定一个Optional,那么获取Optional实例的方法应该表现得更好。但话说回来,他们不能。如果Optional.of过载,除了一个小问题外,它们都可以完成
因为您可以有一个类型为Optional的泛型类型T,所以不能有两个Optional.of方法(一个用于Optional,一个用于T)。如果有人想出了一个可选的
,它有时会阻止一些代码的编译。以下面的代码为例,它将无法编译
package otherCode;
public class Abc<T> {
public static void main(String[] args) {
Abc<B> test1 = new Abc<>();
test1.foo(new A());
test1.foo(new B());
Abc<Base> test2 = new Abc<>();
test2.foo(new A());
test2.foo(new B());
Abc<A> test3 = new Abc<>();
// these two don't compile
test3.foo(new A());
test3.foo(new B());
}
public void foo(A item) {
System.out.println("Foo");
}
public void foo(T item) {
System.out.println("bar");
}
public static class Base {
}
public static class A extends Base {
}
public static class B extends Base {
}
}
package-otherCode;
公共课Abc{
公共静态void main(字符串[]args){
Abc test1=新的Abc();
test1.foo(新的A());
test1.foo(新的B());
Abc测试2=新的Abc();
test2.foo(新的A());
test2.foo(新的B());
Abc test3=新的Abc();
//这两个不可编译
test3.foo(新的A());
test3.foo(新的B());
}
公开作废foo(A项){
System.out.println(“Foo”);
}
公开作废foo(T项){
系统输出打印项次(“bar”);
}
公共静态类基{
}
公共静态类A扩展了基类{
}
公共静态类B扩展了基类{
}
}
在不强制对整个语言进行语言和语法更改的情况下(禁止可选
),自动转换并非易事
我发现,开发人员一般需要一段时间才能掌握Java8。当它第一次出现时,我会看到Map
,而Map
就足够了,或者我确实看到了Optional
。我甚至看到了Map
,而不是简单的Map
。随着时间的推移和人们对语言的掌握,我觉得我们学会了更好地管理这些打字,并获得更明智的打字
我认为Java没有自动进行转换是不幸的,但是对于那些可能有一天需要可选的的可怜的灵魂,我愿意每隔一段时间使用map、flatMap、orElse和of nullable来保持我的输入正常。使用这些方法可以帮助你解决特定的难题
编辑:
我看到,OP看到了流,不是错过了它,就是编辑了它。首先
返回一个可选
。OP打算做什么会影响妥协。他们可以.映射流以去除内部可选项,也可以.filter&.映射流以去除空选项。一行可悲的额外代码。禁止可选的根本没有意义
假设您有一个列表
。以下列表不同:
List<Optional<T>> listA = Arrays.asList(Optional.empty());
List<Optional<T>> listB = Arrays.asList();
System.out.println(listA.stream().findFirst().isPresent()); // true
System.out.println(listB.stream().findFirst().isPresent()); // false
现在,我知道了Java不可能知道的列表中数据的含义。假设这些列表包含调用Callable
s列表的结果。在这种情况下,我的应用程序可能有以下两个重要区别:
- 我调用了N>0个callables,它们都返回了
Optional.empty()
- 我调用了零个可调用项
因此,我真的不想让语言或API假设两者之间没有区别,并将可选
转换为可选
由于List.stream().findFirst()
总是返回一个可选的
,如果不阻止我创建列表
(或集合
,集合
,哈希映射
等),就无法阻止可选的
。因此,您基本上必须完全禁止嵌套泛型,这将是功能的重大损失
我对Optional
的存在非常满意,因为它与语言的其余部分完全一致。如果你不喜欢它们,就不要创造它们;但不要认为这对其他人都是正确的。描述得很好,但你的问题是,如果期权通常不会堆叠并总是平铺,不是更好吗?是基于意见的。第二个转变是