Dmy*_*tro 19 java optional java-8
是不是因为Java 1.8返回Optional对象比抛出异常更可取?我越来越多地看到这样的代码:
public Optional<?> get(int i) {
// do somtething
Object result = ...
Optional.ofNullable(result);
}
Run Code Online (Sandbox Code Playgroud)
而不是这个:
public Object get(int i) {
if(i<0 || i>=size) {
throw new IndexOutOfBoundsException("Index: " + i + ". Size: " + size);
}
// do somtething
Object result = ...
return result;
}
Run Code Online (Sandbox Code Playgroud)
是否意味着我们需要忘记旧方法并使用新方法?什么地方Optional适合?
Mar*_*nik 36
您提供的示例不是 Optional的适当用法.空Optional表示由于调用者无法预测的原因而缺少的值.它是法律调用方法的结果.
您作为"旧习惯用法"呈现的代码会执行输入验证,如果输入无效,则会抛出未经检查的异常.即使您引入Optional,此行为也应保持不变.唯一的区别是返回值Object get(i)可能为null,而返回值Optional<?> get(i)永远不为null,因为Optional实例的特殊状态表示缺少值.
返回Optional而不是可空值的方法的优点是消除了样板代码,该代码必须在尝试对返回值执行任何操作之前进行例行的空检查.纯粹在方法中使用Optional有许多其他优点.例如:
static Optional<Type> componentType(Type type) {
return Optional.of(type)
.filter(t -> t instanceof ParameterizedType)
.map(t -> (ParameterizedType) t)
.filter(t -> t.getActualTypeArguments().length == 1)
.filter(t -> Optional.of(t.getRawType())
.filter(rt -> rt instanceof Class)
.map(rt -> (Class<?>) rt)
.filter(Stream.class::isAssignableFrom)
.isPresent())
.map(t -> t.getActualTypeArguments()[0]);
Run Code Online (Sandbox Code Playgroud)
这里有一个重要的好处是完美的范围控制:t在每个新范围内,对于适合于该处理阶段的类型的变量,重用相同的名称.因此,不是在其使用寿命到期后被迫在范围内使用变量,而是为每个后续变量创建一个新名称,使用这个习惯用法,我们有了我们需要进行的精确最小值.
只是为了感兴趣,您可以equals完全按照Optional执行:
@Override public boolean equals(Object obj) {
return Optional.ofNullable(obj)
.filter(that -> that instanceof Test)
.map(that -> (Test)that)
.filter(that -> Objects.equals(this.s1, that.s1))
.filter(that -> Objects.equals(this.s2, that.s2))
.isPresent();
}
Run Code Online (Sandbox Code Playgroud)
虽然我发现这个成语非常干净和可读,但它目前还没有足够优化,不适合作为一个有价值的选择推荐.但是,Java的未来版本可能会使这一点变得可行.
Bri*_*etz 26
可以平等地滥用异常,空值和可选项.在这种特殊情况下,我认为你可能会滥用可选项,因为你默默地隐藏了一个前提条件违规并将其转换为正常返回.在收到代码中的空选项后,调用者无法区分"我正在寻找的东西不在那里"和"我问了一个无效的问题."
因为Optional是新的,所以也有过度使用的倾向; 希望随着时间的推移,正确的模式将被内化.
可选是null对象模式的示例; 当"没有任何东西"是一个合理的预期结果时,它提供了一种安全的方式来说"没有任何东西".(返回空数组或空集合在这些域中是类似的例子.)无论你是想用null/optional表示"什么都没有"vs一个异常通常是"没有任何东西"是否是一个普遍预期的情况,或者是否特殊.例如,Map.get如果映射不存在,则没有人想要抛出异常; 映射不存在是预期的,而不是例外的结果.(如果我们Optional在1997年,Map.get可能已经返回了Optional.)
我不知道你在哪里听到的建议是,Optional比例外更可取,但是谁告诉你这是不明智的.如果你之前抛出异常,你可能仍然会抛出异常; 如果您之前返回null,则可以考虑返回Optional.