在 forEach 中使用时 OrElseThrow 出错
Error in OrElseThrow when using within forEach
我需要在 forEach 循环中使用 OrElseThrow。
这是我的代码:-
Service.java
public SubscriptionPack saveSubscriptionPack(SubscriptionPack subscriptionPack)
throws LuciVisionApplicationServiceException {
if (subscriptionPackRepository.findByName(subscriptionPack.getName()).isPresent()) {
throw new SubscriptionPackAlreadyExistsException("Subscription Pack With THe Given name
Already Exists");
} else {
List<Channel> channels = new ArrayList<>();
float price = 0;
subscriptionPack.getChannels().forEach(i -> {
// Error Here saying "Unhandled exception type ChannelDoesNotExistException" and
// asking to surround with try Catch but OrElseThrow should have handled it
Channel ch = channelRepository.findByName(i.getName())
.orElseThrow(() -> new ChannelDoesNotExistException("Channel With Given Name
Does Not Exist"));
channels.add(ch);
});
return new SubscriptionPack(subscriptionPack.getName(), null, channels);
}
}
如果我使用普通的 for 循环,它会按预期工作。为什么这对每个循环的 java-8 不起作用?
PS:我的存储库正在返回可选。
我打赌当前异常class结构是:
class LuciVisionApplicationServiceException extends Exception {}
class ChannelDoesNotExistException extends LuciVisionApplicationServiceException {}
有两种解决方案,它们的结果都是RuntimeException
:
ChannelDoesNotExistException
必须扩展 LuciVisionApplicationServiceException
,后者必须是 RuntimeException
的子类型
ChannelDoesNotExistException
必须是 RuntimeException
本身的子类型。
背后的原因很简单。由于传统的 for 循环是方法内部过程代码的一部分,因此在方法级别立即抛出异常。如果将 forEach
与 lambda 表达式一起使用,它会被翻译为匿名的 class Consumer
,这不会在方法级别引发异常(Consumer::accept
),因此除非使用 RuntimeException
的实例,否则您的构造是不可能的:
subscriptionPack.getChannels().forEach(
new Consumer<Channel>() {
@Override
public void accept(final Channel i) { // no throwing exception singature
}
}
);
JLS §11.2.3 的进一步解释(强调我的):
It is a compile-time error if a lambda body can throw some exception class E
when E
is a checked exception class and E is not a subclass of some class declared in the throws clause of the function type targeted by the lambda expression.
我需要在 forEach 循环中使用 OrElseThrow。
这是我的代码:-
Service.java
public SubscriptionPack saveSubscriptionPack(SubscriptionPack subscriptionPack)
throws LuciVisionApplicationServiceException {
if (subscriptionPackRepository.findByName(subscriptionPack.getName()).isPresent()) {
throw new SubscriptionPackAlreadyExistsException("Subscription Pack With THe Given name
Already Exists");
} else {
List<Channel> channels = new ArrayList<>();
float price = 0;
subscriptionPack.getChannels().forEach(i -> {
// Error Here saying "Unhandled exception type ChannelDoesNotExistException" and
// asking to surround with try Catch but OrElseThrow should have handled it
Channel ch = channelRepository.findByName(i.getName())
.orElseThrow(() -> new ChannelDoesNotExistException("Channel With Given Name
Does Not Exist"));
channels.add(ch);
});
return new SubscriptionPack(subscriptionPack.getName(), null, channels);
}
}
如果我使用普通的 for 循环,它会按预期工作。为什么这对每个循环的 java-8 不起作用?
PS:我的存储库正在返回可选。
我打赌当前异常class结构是:
class LuciVisionApplicationServiceException extends Exception {}
class ChannelDoesNotExistException extends LuciVisionApplicationServiceException {}
有两种解决方案,它们的结果都是RuntimeException
:
ChannelDoesNotExistException
必须扩展LuciVisionApplicationServiceException
,后者必须是RuntimeException
的子类型
ChannelDoesNotExistException
必须是RuntimeException
本身的子类型。
背后的原因很简单。由于传统的 for 循环是方法内部过程代码的一部分,因此在方法级别立即抛出异常。如果将 forEach
与 lambda 表达式一起使用,它会被翻译为匿名的 class Consumer
,这不会在方法级别引发异常(Consumer::accept
),因此除非使用 RuntimeException
的实例,否则您的构造是不可能的:
subscriptionPack.getChannels().forEach(
new Consumer<Channel>() {
@Override
public void accept(final Channel i) { // no throwing exception singature
}
}
);
JLS §11.2.3 的进一步解释(强调我的):
It is a compile-time error if a lambda body can throw some exception class
E
whenE
is a checked exception class and E is not a subclass of some class declared in the throws clause of the function type targeted by the lambda expression.