I am looking for an elegant way to create a factory for dependency injection. In my case, the factory simply has to call a one-argument constructor. I found this answer outlining how to use a Function<ParamType, ClassToNew>
for such purposes.
But my problem is: in my case, my ctor declares to throw some checked exception.
What I don't get: creating that Function using a method reference to that constructor doesn't work. As in:
import java.util.function.Function;
public class Mcve {
public Mcve(String s) throws Exception {
// whatever
}
public static void main(String[] args) {
Function<String, Mcve> mcveFactory = Mcve::new;
}
}
tells me about "Unhandled exception: java.lang.Exception" for Mcve::new
. Although this code is not invoking the constructor.
Two questions:
throws Exception
to my main()
does not help )The calculate method should check for an exception and if there is no exception, return the calculated value to the main function i.e. v1+v2 or v1-v2; Else if an exception exists then it should print the error statement and the value that is returned from the calculate method to the main method should be 0.0(Not ...
Checked exceptions are always declared as thrown in the method signature. The signature lets the method's caller know that an exception may occur as a consequence of the call. If the exception does get thrown, the caller must be prepared to do something about it.
The throw keyword in Java is used to explicitly throw an exception from a method or any block of code. We can throw either checked or unchecked exception. The throw keyword is mainly used to throw custom exceptions.
You absolutely should throw an exception from a constructor if you're unable to create a valid object. This allows you to provide proper invariants in your class. In practice, you may have to be very careful.
You need to provide a custom interface ThrowingFunction
which has one method that throws Exception
.
public interface ThrowingFunction<ParameterType, ReturnType> {
ReturnType invoke(ParameterType p) throws Exception;
}
public class Mcve {
public Mcve(String s) throws Exception {
// whatever
}
public static void main(String[] args) {
ThrowingFunction<String, Mcve> mcveFactory = Mcve::new;
}
}
Using this approach results in calling mcveFactory.invoke("lalala");
forcing you to handle the exception thrown by the constructor.
Reason for the error is that the actual function reference you want to store (not 100% sure about the terminology) throws an exception and therefore the types simply do not match up. If you could store Mcve::new
inside a function then whoever calls the function no longer knows an Exception
can be thrown. What would then happen if the exception would actually be thrown? Both throwing the exception and discarding it do not work.
Alternative: if you need to actually retrieve a Function<String, Mcve>
in the end then you need to write a function (or lambda) that invokes the constructor, catches the exception and either discards it or rethrows it wrapped inside a unchecked RuntimeException
.
public class Mcve {
public Mcve(String s) throws Exception {
// whatever
}
public static void main(String[] args) {
Function<String, Mcve> mcveFactory = parameter -> {
try {
return new Mcve(parameter);
} catch (Exception e) {
throw new RuntimeException(e); // or ignore
}
};
}
}
I would argue that the error message itself is at least a bit misleading since you normally see it when actually invoking the method. I can certainly understand the confusion resulting in the first sub-question. It would be clearer (sadly not possible) to state something like
Incompatible types
Function<String,Mcve>
vs.Function<String,Mcve> throws Exception
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With