I have a method that takes an enum as a parameter and returns some information dependent on that parameter. However, that enum contains some values which should not be handled, and should raise an error condition. Currently the method throws an IllegalArgumentException but I would like this to be a checked exception to force callers to catch it (and return gracefully, logging an error). Is there something suitable or should I create my own Exception subclass?
I'm open to other patterns as well. A reasonable reaction would be that all values of the enum should be handled, but that isn't the case. When a new value is added to the enum, I want to make sure that this method does the right thing - alerting a human is preferable to using some default return value in this case.
Thanks for any advice.
You can certainly create a checked exception of your own (such as UnhandledEnumType), or you could catch and handle the IllegalArgumentException. It sounds a little fishy that only some values of the enum should be handled. One of the purposes of an enum is to bind values to a certain set of values, and I would expect all to be handled. If you're worried about new ones being added, you should have a test that tests that all values are properly handled (by using the values() method of the enum to ensure they are all tested).
The questions are:
how "normal" are cases when the method is called with an unsuitable enum parameter?
can you handle these cases gracefully and then continue processing?
From what you describe, it is not "normal" (happens only when a new enum value is added and the method is not updated properly - i.e. when a bug was introduced). So to me this sounds more like a case for RuntimeException (i.e. unchecked). Callers of this method can still catch an unchecked exception if they really want to, but they are not forced to.
OTOH I would try to eliminate the case you describe, by moving the data your method is returning right inside the enum. This way whenever a new enum value is added, there is no way the relevant data could be forgotten.
If you are interested, you may want to check out this tutorial.
How about InstantiationException?
Thrown when an application tries to create an instance of a class using the newInstance method in class Class, but the specified class object cannot be instantiated. The instantiation can fail for a variety of reasons including but not limited to:
the class object represents an abstract class, an interface, an array class, a primitive type, or void
the class has no nullary constructor
Related
I have a method like this:
void method(int number){some code}
and i will call it like this:
method(-1)
is there a way in java to only allow passing positive integers to number parameter other than checking in the method body or making a checked exception?
Declaring a checked exception doesn't make method parameters automatically validated somehow, it just means that the caller is obligated to check whether it was thrown, even if the code calls a literal method(1).
If your application is complex enough, you can use Bean Validation and put a constraint on the method parameter:
void method(#Min(1) int number) { }
This is only worthwhile if you're already using a system complex enough to provide support for it, such as Spring or CDI. Otherwise, just stick to checking in the method body and throwing IllegalArgumentException if the requirements fail. Guava's Preconditions utility can be helpful here.
(Additionally, your code will be much easier to read if you follow the universal Java code standards. Type names start with capitals, but member and parameters names start with lowercase.)
I have a class which offers a public method that must only be called once.
What would be a proper exception to throw in case its called again?
My current candiate is RejectedExecutionException
IllegalStateException may be appropriate, or something similar. For example, calling Thread::start twice would throw IllegalThreadStateException.
I suggest something completely different:
Consider if you can change your design.
The fact that your interface allows to only call a method once puts a constraint on the users of your interface. Interfaces should make it easy to use them "the right way"; and make it hard to use them the wrong way.
So instead of thinking about the exception type to throw ... think about solutions to simply make it impossible to misuse the interface.
For example, make the method private - and invoke only within the constructor of some internal singleton object. That (more or less) guarantees that the method will be called exactly once.
When I throw checked exceptions from a method should I just declare the super class of the exceptions in the method signature or all the different types? If I have the following exceptions:
private class SuperException extends Exception {
}
private class SubExceptionOne extends SuperException {
}
private class SubExceptionTwo extends SuperException {
}
Should the method signature be:
void confirmAccount() throws SubExceptionOne, SubExceptionTwo;
or
void confirmAccount() throws SuperException;
In the last method signature, how do I tell other developers what exceptions that could be thrown from the method? If the different sub types need different handling?
The interface should be as stable as possible. So probably Super. Many libraries use the "Super" strategy, because exception specs cause far more annoyance in maintainability than readability or safety they add. Even the IOException is a Super that nearly all Java library code uses instead of declaring more specific exceptions. (But when they do declare more specific exceptions, it's because the contract is that more general IOExceptions won't be thrown. Read on.)
You might list Sub1 and Sub2 if you really do want to say each of those exceptions can be thrown, but don't want to say that any derivative of Super can be thrown. Perhaps Sub1 is NumberCrunchException and your method calls crunchNumbers() and users of your method can be assured that's the only exception-ful thing your method does. In that case the specific strategy is better.
If the different sub types need different handling, then definitely declare the two different exceptions. Never expect the developer using your method to guess that you are actually throwing different types of exceptions.
If you declare two distinct exceptions, and the user knows from the Javadoc that they are actually descendents of the same class, the user may choose to catch them both with a catch (SuperException e) rather than two individual catch clauses. But it depends on the user's choice.
If you don't declare them separately, your IDE is not going to add the appropriate #Throws to your Javadoc comment. And your Javadoc will therefore only indicate that you're throwing SuperException, which will leave the user in the dark. Solving this by just putting it in the text of the comment is not a real solution. If any tool is using reflection to determine what your method throws, it will not see the individual exceptions in the array returned from Method.getExceptionTypes().
If the functionality expected of the different exceptions is more or less the same and it's just a matter of how they will appear in the logs, it may be better to just use the parent exception, with different messages.
The throws clause is there to convey useful information to the calling method about what might go wrong during invocation of this method. That means that how specific you are will depend on how much information you want to convey; and that will be application-dependent.
For instance, declaring throws Exception is almost always a bad idea: the information this conveys is just "something might go wrong", which is too vague to be useful. But whether calling classes are going to need perfectly fine-grained information in the throws clause is something you need to decide by looking at your program. There's no set answer.
Is it possible to convert a method reference (e.g. SomeClass::someMethod) to a MethodHandle instance? I want the benefits of compile-time checking (ensuring that the class and method exists) as well as the ability to introspect the method using the MethodHandle API.
Use-case: I've got code that needs to execute if and only if the request was not triggered by a specific method (to avoid endless recursion). I want a compile-time check to ensure the class/method exists but a runtime check to compare the caller to the method.
So to recap: Is it possible to convert a method reference to a MethodHandle?
Well, if you can afford the additional overhead and security implications, you can use a Serializable functional interface and decode the serialized form of the method reference instance to find the target like demonstrated in this answer or brought up again with this question and its answers.
However, you should really rethink your software design. “Avoiding endless recursion” shouldn’t be fixed by decoding some kind of parameter object, especially not if your assumption is, that this actual argument value represents the caller of your method. How would you ever enforce this strange relationship?
Even a simple code change like referencing a method which delegates to the other method would break your check. Here is a simple example showing the subtle problems with your approach:
public class SimpleTest {
public static void main(String... arg) {
run(SimpleTest::process);
}
static void run(BiConsumer<Object,Object> c) {
c.accept("foo", "bar");
}
static void process(Object... arg) {
Thread.dumpStack();
}
}
When running this program it will print something like:
java.lang.Exception: Stack trace
at java.lang.Thread.dumpStack(Thread.java:1329)
at SimpleTest.process(SimpleTest.java:16)
at SimpleTest.lambda$MR$main$process$a9318f35$1(SimpleTest.java:10)
at SimpleTest$$Lambda$1/26852690.accept(Unknown Source)
at SimpleTest.run(SimpleTest.java:13)
at SimpleTest.main(SimpleTest.java:10)
showing that the method reference within the generated instance is not the expected SimpleTest::process but instead SimpleTest::lambda$MR$main$process$a9318f35$1 which will eventually invoke process. The reason is that some operations (here varargs processing) are not performed by the generated interface instance but a synthetic method instead, just like you had written run((a,b)-> SimpleTest.process(a,b)). The only difference is the name of the synthetic method.
You shouldn’t design software relying on such fragile introspection. If you want to avoid recursion, a simple ThreadLocal flag telling whether you are already inside your specific method would do the job. But it might be worth asking yourself why your API is provoking endless recursion in the first place; there seems to be something fundamentally wrong…
I need to create an object of some type.
The class of the object has just one constructor (one that I've written).
My program receive requests to create instances of an objects with a parameter ID.
I want to stop the constructor if the ID parameter contains a char that is not a digit.
I cannot check the parameter before, since I'm not the one who calls the constructor.
Make the constructor private and expose a static factory method, that will validate and return a new instance of the object if the parameter is valid.
The only way to "stop" a constructor is to throw an exception. Bearing in mind of course that the caller is supposed to "know" about this exception and be able to handle the case where the constructor fails.
Throwing an exception from the constructor doesn't stop the object being created though, It just makes the assignment of its reference to a variable fail and the reference unavaliable (and therefore eligible for garbage collection) unless you make the mistake of passing this to an external method from the constructor itself. (Which you shouldn't do anyway.)
How to solve this depends on what you want to happen when an illegal character is given, which in turn depends on what object we're talking about, and how the consuming library is using it.
The most reasonable thing to do would be to throw an IllegalArgumentException, and this is what I'd suggest you do.
However, it might make sense to just return null, too, even though I'd strongly recommend against it (you can't do this directly in the constructor, but you can create a factory method that does this).