0

I have a task to "move" my throws Exception from main() to lambda-expression. That means that when exception occurs in Lambda, the program uses throws from main. The problem is that I can't create any other interface which could automatically do that, because my teacher said to use only interface from java.util.Function and I've been looking in the internet, but mostly there are answers like "create new interface".

public static void main(String[] args) throws IOException {

  Function<String, List<String>> flines = (String x) -> {
      Stream<String> streamString = Files.lines(Paths.get(x)); //Should throw Exception from main if IOException

      List<String> tmp = streamString.collect(Collectors.toList());

      return tmp;

  };
Szadury
  • 3
  • 2
  • 1
    The only way you can do this without creating a new interface type is to catch the exception inside the lambda, and rethrow as an unchecked exception (or otherwise handle). – Andy Turner Nov 02 '18 at 09:18

2 Answers2

0

You can catch the IOException inside the lambda expression, wrap it in a RuntimeException, catch that exception in the main, extract the wrapped IOException and throw it:

public static void main(String[] args) throws IOException 
{
    Function<String, List<String>> flines = (String x) -> {
      List<String> tmp = null;
      try {
        Stream<String> streamString = Files.lines(Paths.get(x));
        tmp = streamString.collect(Collectors.toList());
      } catch (IOException ioEx) {
        throw new RuntimeException (ioEx);
      }
      return tmp;
    };

    try {
      List<String> lines = flines.apply ("filename.txt");
    }
    catch (RuntimeException runEx) {
      if (runEx.getCause () instanceof IOException) {
        throw (IOException) runEx.getCause ();
      }
    }
}
Eran
  • 387,369
  • 54
  • 702
  • 768
  • I'm not convinced you need to go to the effort of checking the cause. OP says "Should throw Exception from main if IOException" - just propagating the `RuntimeException` meets that criterion, since that is an `Exception`. – Andy Turner Nov 02 '18 at 09:28
  • Yeah from what I see that is the only way I cant do this with wrapping to RuntimeException. I think that is what I've been looking for. Thanks!, – Szadury Nov 02 '18 at 10:03
0

You can only throw a unchecked exception as Function doesn't declare any checked exception in the signature of its functional interface.
So you can only explicitly throw a RuntimeException (and its subclasses) instances from the lambda body such as :

  Function<String, List<String>> flines = (String x) -> {
      try{
        Stream<String> streamString = Files.lines(Paths.get(x)); 
        List<String> tmp = streamString.collect(Collectors.toList());
        return tmp;
      }
      catch (IOException e){
        throw new RuntimeIOException(e); 
      }

  };

But declaring throws IOException in the main() method is so helpless as it will never be thrown it but if you catch the runtime exception in the Function client and that then you re-throw a IOException. But that is a lot of things for almost nothing.

davidxxx
  • 125,838
  • 23
  • 214
  • 215
  • I think that is what my teacher wanted to see, but what are the differences between throwing it inside lambda and by using IOException from main? – Szadury Nov 02 '18 at 10:05
  • The difference is that throwing a runtime exception (which is or derives from `RuntimeException` doesn't need to be explicitly handled (catching or throwing) while a checked exception requires to be handled. – davidxxx Nov 02 '18 at 10:28