Consider the following java code:
public void write(FrameConsumer fc) throws FFmpegFrameRecorder.Exception{
frameStream.forEach(n -> fc.consume(n));
}
In this case "frameStream" is a Stream of Objects that can be passed to the "consume" method, and fc is a class containing the "consume" method. Another important note is that the "consume" method throws a "FFmpegFrameRecorder.Exception", which I would like to pass on to whatever method calls "write" in the future.
However the above code does not compile, because: "Unhandled exception type FFmpegFrameRecorder.Exception Java(16777384)". Why is that?
Best regards, CCI
EDIT: Puting a try_catch block inside the lambda expression does not solve the problem either, hence:
public void write(FrameConsumer fc) throws FFmpegFrameRecorder.Exception{
frameStream.forEach(n -> {
try {
fc.consume(n);
} catch (FFmpegFrameRecorder.Exception e) {
throw e; //**this part does not compile**
}
});
}
(As provided by @Soumya Manna) does not compile either. The compiler still wants for the program to handle the "FFmpegFrameRecorder.Exception e" as it is thrown.
CodePudding user response:
You cannot do this in lambda. You may simple write for loop and throw it or use try-catch block in lambda and throw Runtime exception there.
CodePudding user response:
You could wrap the exception in a RuntimeException
and then unwrap it:
public class ExceptionWrapper extends RuntimeException {
public ExceptionWrapper(Throwable cause) {
super(cause);
}
}
// ...
public void write(FrameConsumer fc) throws FFmpegFrameRecorder.Exception {
try {
frameStream.forEach(n -> {
try {
fc.consume(n));
} catch(FFmpegFrameRecorder.Exception e) {
throw new ExceptionWrapper(e);
}
});
} catch(ExceptionWrapper e) {
throw (FFmpegFrameRecorder.Exception) e.getCause();
}
}
CodePudding user response:
The code is not compiling because the forEach
method of the Stream
class does not allow you to throw a checked exception from the lambda expression passed to it.
The forEach
method is a terminal operation on the stream that consumes the elements of the stream and applies the given lambda expression to each element. It does not allow you to throw any checked exceptions from the lambda expression, because it does not have a throws
clause in its signature.
To handle the FFmpegFrameRecorder.Exception
exception thrown by the consume
method, you have a few options:
List item
- You can wrap the call to the consume method in a try-catch block inside the lambda expression, and handle the exception there.
- You can modify the
write
method to throw theFFmpegFrameRecorder.Exception
by adding a throws clause to its signature. This will allow the exception to be passed on to the caller of the write method. - You can modify the
consume
method to throw a different type of exception that is not a checked exception, such as a runtime exception. This will allow you to use theforEach
method without having to handle the exception inside the lambda expression or throw it from thewrite
method.
Here is an example of how you can modify the write
method to handle the exception using option 2:
public void write(FrameConsumer fc) throws FFmpegFrameRecorder.Exception {
frameStream.forEach(n -> {
try {
fc.consume(n);
} catch (FFmpegFrameRecorder.Exception e) {
throw e;
}
});
}
This will allow the FFmpegFrameRecorder.Exception
to be passed on to the caller of the write
method.