我是Java可选对象的新手,但我看到此代码是由另一个开发人员编写的,但我没有得到它:
String t = null;
Optional.ofNullable("notnull")
.orElse(
Optional.ofNullable(t).orElseThrow(() -> new Exception("MyException"))
);
为什么此代码引发异常?为什么甚至转到“ orElse”分支?
这是因为执行顺序有些奇怪吗?那么在评估orElse分支之前是否未设置第一个可选值?
答案 0 :(得分:8)
Optional.ofNullable(t).orElseThrow(() -> new Exception("MyException"))
流从不会被调用,但是方法本身会被执行。这意味着方法参数也将传递给它。因此,无论传递给第一个Optional.ofNullable("notnull").orElse(...)
调用的值如何,都将调用orElse
部分。
如果您不希望发生这种情况,则需要通过Optional.ofNullable(t).orElseThrow(() -> new Exception("MyException"))
,如下所示:
Optional.ofNullable
仅在调用Supplier
流时才调用供应商。
请注意,您需要一个String t = null;
Optional.ofNullable("notnull")
.orElseGet(
() -> Optional.ofNullable(t).orElseThrow(() -> new RuntimeException("MyException"))
);
而不是已检查的异常,才能从供应商处中断。
答案 1 :(得分:5)
这是因为 orElse()
中的代码将始终被评估。换句话说,即使您指定了非空的Optional
,它也会被执行,这就是抛出public static void main(String[] args) {
try (Scanner in = new Scanner(System.in)) {
Integer no;
do { // this is some flaky code but it works for this purpose
try {
no = Integer.parseInt(in.nextLine());
break;
} catch (Exception e) {
System.out.println("please enter only a numeric value");
}
} while (true);
System.out.println("You entered string " + no);
int z = 0, y = 0;
char[][] arr = new char[no][];
for (z = 0; z < no; z++) {
String s = in.nextLine();
String[] arrOfStr = s.split("");
arr[z] = new char[arrOfStr.length];
for (y = 0; y < arrOfStr.length; y++) {
System.out.println();
arr[z][y] = arrOfStr[y].charAt(0);
}
}
for (char[] charArr : arr) {
for (char c : charArr) {
System.out.println(c);
}
}
}
}
的原因。
如果您查看 Java Optional – orElse() vs orElseGet() 文章的Exception
部分,则可以在他们的示例中看到以下内容:
即使具有非空的Optional,我们也可以轻松推断出orElse()的参数是经过评估的。
答案 2 :(得分:3)
您写的是这样的:
String t = null;
String myException = Optional.ofNullable(t).orElseThrow(() -> new Exception("MyException"));
Optional.ofNullable("notnull").orElse(myException);
对orElse
的{{1}}部分进行评估,然后才知道您的值是否为空。如果要进行Optional
评估,请考虑"Lazy"
方法。
答案 3 :(得分:2)
问题按执行顺序。 它正在尝试计算.orElse(...)的值,并在.orElseThrow上抛出MyException。
换句话说,如果t不为null,则执行流程如下:
1)计算
的值<Dialog.Container visible={this.state.dialogVisible} contentStyle={{height: 300, width: 300, paddingBottom: 105}}>
<Dialog.Title>Edit Your Note</Dialog.Title>
<Dialog.Input paddingHorizontal = "0%" height = "100%" width="100%" multiline={true} onChangeText={(nm) =>
this.setState({ newNote: nm })}
value={this.state.newNote}></Dialog.Input>
<Dialog.Button label="Cancel" onPress={() => this.handleCancel(e.ans)} />
<Dialog.Button label="Save" onPress={() => this.handleSave(e.idx, e.ans)} />
</Dialog.Container>
2)使用
中(1)的值.*(?:https?:\/\/)?(?:www\.)?[a-z-]+\.(?:com|org)(?:\.[a-z]{2,3})?.*
答案 4 :(得分:2)
之所以可以得到预期的结果,是因为在Java中,在调用带有参数的方法之前,JVM在评估参数值之前所做的事情。
这就是select top 100
ih.streetname,
ih.district,
s.value
from vw_pn_intervalshouse ih
inner join vw_pn_street s on s.id = ih.streetname
CROSS APPLY STRING_SPLIT(ih.intervalhouse, ',') s;
调用的参数值:
.orElse()
由于Optional.ofNullable(t).orElseThrow(() -> new Exception("MyException"))
引用了t
,因此会引发异常。
答案 5 :(得分:2)
我真的很想知道为什么以这种方式编写此代码。似乎需要触发一个异常,并在可选项中添加一个明确的NULL值。
如前所述,使用orElse()
代替orElseGet()
时,无论T的值如何(例如Optional<T>
),都会评估该方法。
我会使用一种更好的时尚和色彩搭配:
String value = "notnull"; // could be null
Optional.ofNullable(value)
.orElseThrow(MyException::new);
如果该值为NULL,则触发异常。
请注意,您可以使用方法引用来调用异常
答案 6 :(得分:2)
关于Optional,您应该注意以下几点:
如果知道要包装的值是否为空,请使用Optional.of()或Optional.empty()。如果不确定(例如,值是您从其他地方获取的变量),请使用Optional.ofNullable()
Optional.orElse()和Optional.orElseGet()之间存在重要区别。
orElse
取一个已经计算出的值,如果提供了一个表达式,则立即执行该表达式并对其求值。 这正在有问题的代码中发生。因此,应将此else变量用于已经可用的值或基元。
orElseGet
采用的供应商功能仅在评估可选链并请求替代值时运行。如果替代值的产生或计算成本很高,则应使用此方法。
// Fine
Optional<String> name = Optional.of(someValue).orElse("defaultName");
// But this:
Optional<String> name = Optional.of(someValue).orElse(db.queryName());
// Is better written as following, as it saves you from an expensive operation
Optional<String> name = Optional.of(someValue).orElseGet(() -> db.queryName());