NOTE: This question is about finding a proper name for an exception where the condition for throwing the exception has not actually happened (eg. preventing a StackOverflow by throwing a StackOverflowException
before an overflow can occur)
I have a FooList
class that has bounds on the number of elements it can contain. The constructor takes an initial list of elements, and more elements can be added, up to the limit.
The question I have is this. Having a full FooList
is not exceptional. I decided that it would probably be best if I provided the client with a way of checking to see if there was room in the FooList
before trying to add something to it (hasRoom
). However, this doesn't really stop them from calling add
without checking first.
I decided that in this case, it may be appropriate to throw an exception. However, I'm not exactly sure what to call it. As I stated, having a full FooList
is not particularly exceptional, and is in fact a perfectly valid state. So throwing a FooListFullException
doesn't feel right. However, throwing an UnableToAddFooToListBecauseFooListIsFullException
also doesn't feel right.
public class FooList {
FooList(List<Foo> foos) {
Objects.requireNonNull(foos);
if (foos.size() > 6) {
throw new IllegalArgumentException("foos must not contain more than 6 Foos");
}
if (foos.size() < 1) {
throw new IllegalArgumentException("foos must contain at least 1 Foo");
}
this.foos = foos;
}
void add(Foo foo) {
Objects.requireNonNull(foo);
if (!hasRoom()) {
throw new XException("no more room in list");
}
}
boolean hasRoom() {
return getNextEmptyIndex() != -1;
}
private List<Foo> foos;
}
In what way could I name the exception to indicate that an add
operation is unable to complete, OR, is there a better way to get this across to the user/client?
4 Answers 4
I think you're looking at this the wrong way.
You are correct that throwing an exception is the right thing to do. The fact that a full list is a valid state has little to do with the exception, though.
The exception in this situation is used to highlight that the state transition is invalid. That is to say, the caller is trying to push the object from a valid state to an invalid state.
I'm not a Java dev, so I don't know which specific exception to throw in this case. But, in C#, the InvalidOperationException
is just for this kind of thing. Its MSDN entry reads "The exception that is thrown when a method call is invalid for the object's current state."
I'd recommend you follow that pattern when naming your exception. Make it clear the operation is invalid, not the state.
-
2There is an
IllegalStateException
that, although the javadoc states it represents an illegal state in the JVM or java application, most people, even in the JRE, use it to represent that the object is in an illegal state for that method to be called.Zymus– Zymus2016年04月23日 16:59:11 +00:00Commented Apr 23, 2016 at 16:59 -
Java has
UnsupportedOperationException
, which fits the bill if you only read its description. But it's usually thrown by unimplemented methods of an interface (an antipattern from the early days of Java) and most Java programmers probably associate it with that.Kevin Krumwiede– Kevin Krumwiede2016年04月27日 06:43:14 +00:00Commented Apr 27, 2016 at 6:43
Exceptions are probably the best way to go. That way, whomever uses your class will get a well known, standardized notification that what they are attempting is a no no.
You should make your own custom Exception (e.g., OverFooListLimitException
). Do include Exception at the end of your custom exception class name, so that everyone who sees it will know the purpose of this class.
public class MyOwnException extends Exception {
public MyOwnException () {
}
public MyOwnException (String message) {
super (message);
}
public MyOwnException (Throwable cause) {
super (cause);
}
public MyOwnException (String message, Throwable cause) {
super (message, cause);
}
}
Replace the MyOwnException
with whatever you name your custom exception.
Example Custom Exception came from How to create a custom exception type in Java?
-
I was thinking about
FooLimitExceededException
, at the same time however, the limit wasn't really exceeded, as the exception was thrown before it could be exceeded, which I think is where the problem lies.Zymus– Zymus2016年04月23日 04:01:57 +00:00Commented Apr 23, 2016 at 4:01 -
2Here's another: FooListOverflowException.Martin Maat– Martin Maat2016年04月23日 05:23:56 +00:00Commented Apr 23, 2016 at 5:23
A Java Queue with a capacity limit throws an IllegalStateException. Personally, that seems like a poor choice of exception to throw, but you might want to do that to be "compatable" If you create your own Exception, consider extending IllegalStateException.
If I had to use an exception in this case, I would keep it as simple as possible and name it something like ContainerFullException
or ListCapacityExceededException
.
However, I'm not sure it's the best choice here. Since you've indicated that the list being full is actually not exceptional, that might be a good indicator not to use an exception. Exceptions can be expensive to throw (stack unwinding, etc.) and can, IMO, lead to more complex calling code.
Could add()
on your list simply return a boolean
which is true if the item was added and false otherwise? What is the calling code supposed to do if the list is full? If the value that couldn't be added has to be saved for retry later, this would be cleaner when working with a return value vs. trying to put logic in the catch
block.
-
Might want to use "offer()" instead of add, as done by a Queue.user949300– user9493002016年04月23日 08:26:21 +00:00Commented Apr 23, 2016 at 8:26
Optional<Settable<T>>
which would avoid race conditions though another thread could still observe an unset element.