Mostly technical stuff with some interesting moments of life

Referring Methods that Throw Exceptions in Java

No comments
The ability to refer (pass) methods in Java 8 is a convenient feature, however, as a programmer you might face the situtaion where some code that seemingly follow the correct syntax to refer a method that throws an exception gives a compilation error of anUnhandled Exception, which doesn't go away by wrapping the call in a try/catch or adding a throws clause to the method signature. See the following code,
import java.util.function.Function;

public class PassingMethodsThatThrowExceptions {

    public static int addOne(String value) throws NotANumberException{
        int v = 0;
        try{
            v = Integer.parseInt(value);
        } catch (NumberFormatException e){
            throw new NotANumberException();
        }
        return v+1;
    }

    public static void increment(Function<String,Integer> incrementer, String value){
        System.out.println(incrementer.apply(value));
    }

    public static void main(String[] args) {
        increment(PassingMethodsThatThrowExceptions::addOne, "10");
    }
}
This is a simple code, which has
  • an addOne function that takes in a String value representing a number then adds 1 to it and returns the result as an int.
  • an increment function that simply takes a function, which can perform the increment and a value then apply the function to the value.
  • the main method that calls increment with addOne function and value "10"
Note. addOne function is declared to throw possible exception of type NotANumberException (the type of exception is NOT important here).
This code will result in following compilation error,
    Error: java: incompatible thrown types exceptions.NotANumberException in method reference
If you use an IDE such as IntelliJIDEA it'll show Unhandled Exception: NotANumberException for the increment method call in mainand adding try/catch will not work.
What's going wrong here? It's actually a mistake on your end.
The increment function expects a function that takes a String and returns an int, but you forgot to mention that this method may also throw an exception of type NotANumberException.
The solution is to correct the type of incrementer parameter in increment function.
Note. you'll need to write a new functional interface because you can't add throws NotANumberException to thejava.util.function.Function interface that's used to define the type of incrementer parameter here.
Here's the working solution in full.
public class PassingMethodsThatThrowExceptions {
    public interface IncrementerSignature{
        public int apply(String value) throws NotANumberException;
    }

    public static int addOne(String value) throws NotANumberException{
        int v = 0;
        try{
            v = Integer.parseInt(value);
        } catch (NumberFormatException e){
            throw new NotANumberException();
        }
        return v+1;
    }

    public static void increment(IncrementerSignature incrementer, String value) throws NotANumberException {
        System.out.println(incrementer.apply(value));
    }

    public static void main(String[] args) {
        try {
            increment(PassingMethodsThatThrowExceptions::addOne, "10");
        } catch (NotANumberException e) {
            e.printStackTrace();
        }
    }
}
Also, note this is NOT something to do with referring methods or Java 8 in general. You may face a similar situation even in a case where you implement a method of an interface and in the implementation you add the throws SomeException to the signature. Here's a stackoverflow post you'd like to see on this.
Hope this helps!

No comments :

Post a Comment