Java: Exception in constructors: Problematic or not? - java

I am recently thinking about if throwing constructor from Java is good or not. Currently this is what I gathered:
Can constructors throw exceptions in Java?
Here, Mr. StackOverflow (aka Jon Skeet) does not seem to hold anything against it, but he did hint about having subclass throwing exceptions. What will happen (anything bad?) when subclass throws exceptions?
http://futuretask.blogspot.com/2006/05/java-tip-10-constructor-exceptions-are.html
This blog post "Constructor Exceptions are Evil" tells me a way to show that constructor exceptions could be dangerous. However, the example seem to be really esoteric. Is there any real danger here?
I am thinking that if static factory methods (Effective Java 2nd ed., Item 1) are used instead of public constructors, we could safely remove the exceptions from constructors to the static factory method. Is this a valid way to avoid constructor exceptions and is this useful or used in anywhere?
Any inputs are helpful & appreciated. Thanks!

There is nothing wrong with exceptions in constructors (or factory methods, either way is fine). sometimes, doing too much work in a constructor can be a poor design, and may make sense to move to a factory method.
the only thing that point 2 proves is that exceptions in constructors are not an adequate security mechanism for protecting a class from evil usage. however, there are any number of ways to subvert such a design, which is why the only way to truly run secure code in java is running with a SecurityManager. so point 2 is just a straw man argument.

My point about a subclass throwing an exception is a situation like this:
public class Parent {
private final InputStream stream;
public Parent() {
stream = new FileInputStream(...);
}
public void close() throws IOException {
stream.close();
}
}
public class Child extends Parent {
public Child() {
// Implicit call to super()
if (someCondition) {
throw new RuntimeException();
}
}
}
Now the Child class really should call close() if it's going to throw an exception. Of course, if close() is overridden by yet another layer of inheritance, that could also cause problems. Just another example of how inheritance gets messy.
I still think it's basically fine for constructors to throw exceptions. Even your second link was more about an evil way of capturing the not-successfully-constructed object rather than really about constructor exceptions being evil - it certainly doesn't give any reasons for not throwing exceptions from constructors. It doesn't even give the messy situation I mentioned.
Factory methods could potentially help, but as far as the caller is concerned the result is the same: they don't get to see the partially-constructed object. Unless you really need to do something like clean-up on an object which was constructed but then failed some element of validation, I don't think that should be a reason to use factory methods instead of constructors. (There are other reasons to do so, but that's a different matter.)

I believe throwing exceptions from constructors is fine, more so the one's which checks for the preconditions to a successful object creation, example IllegalArgumentException.
However, I do not believe that constructors are the right place to handle business logic or throw business exception/ custom exceptions.
As for the reasons cited to not throw an exception, IMHO they are quite contrived; bottom line is if a careless developer wishes to do something evil he can find numerous ways to do it and there's no stopping till the developer does a self review of the code/ follows best practices.

Related

Catching generic Exception in a toString implementation - bad practice?

I have a domain model class which has a toString implementation that looks like this:
public String toString() {
try {
return getX() + "\n"
getY() + "\n"
getZ(); //etc.
} catch(Exception e) {
throw new RuntimeException(e);
}
}
The methods getX(), getY() and getZ() are not simple getters, they can perform lookups in the background, generally a lookup to a static map of predefined key-value pairs. Some of them had throws SomeCheckedException in their signatures.
My impression is that this is bad practice and a "code smell". The fact that toString() even needs this check is to me a symptom of bad design. But I'm asked by a colleague, what exactly is wrong with catching the generic Exception in a toString(), since the caught Exception is propagated further.
I believe it violates at least the KISS principle, since a simple method like toString() here is indicated as requiring special exception handling.
So is it code smell to have a catch-all block in a toString()?
Answers I found were either for the general scenario of catching generic Exception and I agree with most of them, that if you're doing a generic error handling mechanism or a batch then it's expected to work on generic exceptions. This argument was unconvincing in our discussion, so I'm curious of other opinions.
For the toString() method, catching Exception is not necessarily a bad practice. However, re-throwing it is the problematic part.
The contract for toString() is:
... In general, the toString method returns a string that "textually represents" this object. The result should be a concise but informative representation that is easy for a person to read...
In Effective Java 3rd Edition (Item 12), Bloch further insists:
When practical, the toString method should return all of the interesting information contained in the object.
So, if this requires calling methods that may throw checked exceptions, then so be it, and it makes a lot of sense to catch these exceptions.
However: raised checked exceptions provide information about the state of the object. Consistently with the goal of toString, it may be a good idea to include the exceptional condition in the message returned by toString.
As for why it's a bad idea to throw exceptions from toString, this post provides a great answer.
Recommendation: Catch the checked exceptions using their specific exception type, and integrate this fact in the toString() message, instead of propagating it.
Yes this is bad practice.
The intention of the toString method is to provide a programmer readable representation of your class. You shouldn't include any method calls in this method, including getters.
In fact, I would consider not autogenerating these methods smelly, but assuming you are not comfortable or able to use an IDE that would produce them for you, I would recommend including a reference to all the fields on the object, and the class name of the object, as is done by the intellij toString method
The main reason not to catch generic Exception at any place is that it will include RuntimeExceptions too, which should not be catched on normal circumstances, because they always represent a bug in the program. It's better to let them be propagated and arise, so that the developer can notice it and eventually fix it.
I don't know if any additional good practice checks shall be applied in the case of toString methods, but I'm sure at least the general rule should be applied.
So, the best practice is always to catch only checked exceptions, and then either recover, either rethrow them, or either rewrap them into another exception (which is your case).
Should the "normal flow" be interrupted by a failing toString() method? If the answer is no, you should make the toString() method "work". Catching an exception an reflecting this in the result is one possibility, or a simple log output.

Should I declare all exceptions thrown from a method in the method signature or just the super class of the exceptions?

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.

Programmatically distinguish exceptions

The type of an exception is often enough to handle it properly (for example you try to open a file and get a FileNotFoundException). However there are cases where you might catch multiple exception of the same type. For example, an IllegalArgumentException that can be caused by more than one argument. The IllegalArgumentException does not add any additional methods (or public fields) to the Throwable interface (accoding to the online javadoc) which means that the only information that you can rely on are the nested exception (which may or may not exist) and the message (which is for human consumption).
I don't like the idea of extending IllegalArgumentException to add structured information to it, because other people would have to learn the new class. And I don't like the idea of littering projects with very specific exception classes.
Using the message field is also a bad idea because it's not meant for programmatic access.
I think IllegalArgumentException should have included details such as the class function and argument(s) in question. And in general custom exceptions should provide additional detail (other then just their type) for a more fine grained exception handling.
What are considered generally the best practices for designing exception classes, and handling exceptions of the same type?
As a general rule, I think it is ideal to have one class of exception per "type of action a caller might reasonably want to take". Of course, for one's own custom exceptions there could be a boolean or enum field providing some extra disambiguation, rather than creating trivial subclasses.
In your specific case I'm not convinced that trying to handle the exception is a good idea. RuntimeException and its subclasses usually represent coding issues, and the same is true of IllegalArgumentException. If the argument is illegal it shouldn't be passed in in the first place.
If you're in a situation where you're not sure if an argument is valid (maybe it's user input, or maybe you don't know the specific object you're calling the method on) then a better approach would be to have some way of checking the validity of the argument before passing it. Rather than say "do this" and catch the exception, ask "can I do this?" before calling.
Exception classes should be designed so as to provide all that is needed when they are caught. Note that try/catch statements are actually a form of type switch, so in general it is cleaner to create additional exception classes rather than confuse program logic by nesting too many if's within catch clauses.
It has to be said that catch clauses are not very convenient if you want to organize your error handling code in an object oriented fashion, so there are different trade offs to keep in mind.
Note that standard exception classes do have information available on what piece of code caused the exception, even though I would not advise you to base on it your error handling logic.
If the current exception was thrown in a catch clause for a different exception this should be available with the getCause() method, while the getStackTrace() should provide access to the stack of calls that were active when your exception was thrown.
Again I don't advise you to use this information except for debugging purposes.
Its true that the predefined exception classes are very general. But if you want more specific details about the exceptions then you should go for user defined exceptions. you should create your own exception classes with any level of details!
here is the pseudo code:
public class TooManyArguments extends exception{
public String toString(){
return ("..whatever information you want to give for this exception..")'
}
}
and whenever you encounter exceptional situation throw an instance of this class
throw new TooManyArguments();

Omitting throws declarations in derived classes

Consider the following interface:
public interface Generator {
String generate() throws IOException;
}
and the following implementation:
public class EmptyStringGenerator implements Generator {
#Override
public String generate() {
return "";
}
}
Note that I omitted the throws IOException part of the signature specified in the Generator interface. Yet there is no compiler error, no compiler warning, not even the #Override annotation complains.
I am aware that this is working as intended. I would, however, like to know the intent behind this. If my method does not actually throw an IOException, it would be fine to just not throw it, I do not have to remove it from the signature. But if I do remove it from my method signature in EmptyStringGenerator, I am forcing all current and future subclasses of this class to forego the possibility of throwing an exception that is actually specified in the interface.
This, to me, sounds like a feature that does not really bring you any benefit (apart from saving a couple of keystrokes, which is not really a benefit at all), but has the potential to be a terrible mistake, when actually used.
So my question, effectively, is this: What is the point of omitting throws exceptions in derived classes? What is the problem that this possibility solves? Why is this allowed?
UPDATE
For people asking "but where is the harm in that?", here is my example from one of my comments. It is not far-fetched, by the way, because that is exactly what I am dealing with right now:
Programmer A specifies interface I. Programmer B writes implementation class X, but forgets to add the throws. He also never notices, because there is not even a warning being thrown here. Programmer C writes implementation class Y, inheriting from class X, he even specifically also wants to put the throws there, because he is gonna throw. But even though the interface stipulates it, he is now not allowed to do so anymore, because of B's oversight. He is effectively not allowed to use that exception here anymore. That's a pretty big harm. Especially if class X is not under your control.
If you omit the throws exception in derived classes you can call the method of the derived class without having to catch the exception.
You make sure that subclasses of EmptyStringGenerator also don't throw an exception. Otherwise it would not be sure for the compiler if the method call can cause a checked exception which the code must handle. In that case the throws wouldn't make sense at all.
Based on your class decleration, campare these two conditions:
EmptyStringGenerator generator = new EmptyStringGenerator();
generator.generate();
if you create an instance of EmptyStringGenerator like above, Since you omit the throws in EmptyStringGenerator, the above code indicates you are using the class itself, which of course has nothing to do with the interface, so the code works just fine.
but if you intend to use the interface instead of the class, like this:
Generator generator = new EmptyStringGenerator();
generator.generate();
than the compiler would actually remind you that there is an unhandled exception, you must handle it with a try-catch or throw it, otherwise the code will not compile.
if you use any subclass of EmptyStringGenerator in the latter manner, the same compile error will occur. So omitting the throw does not actually rlease you from handling the exception. It's only natural not to throw exception in a class and its subclasses when there is none to throw, but When you are calling the method through the interface, the exception still has to be handle.
In Java its OK and normal that you can make your classes less restrictive when implementing or extending that is a design decision of the Java developer. I can not say why Sun decided it this way and of course I can understand your problem with it, but the current way also has some benefits.
I see an Interface as a possibility to have multiple implementations for one job. For example the List classes which have different implementations for different needs. But they can all be used via the List interface. Lets say the remove method throws a CheckedException if the element is not part of the list. Now if am not able to be less restrictive in my implementations all List classes must throw this CheckedException, even they do not need or use it.
So if I use the remove method internally in my Class I am forced to handle the CheckedException. If I use my List class directly without the Interface I am forced to catch the exception. But for both cases I am pretty sure I do not need it and it will never happen. So with the current approach I can save a lot of "try catch ignore" blocks.
An other benefit of the current solution is that a class can easily match similar Interfaces.
So for example in one lib someone added a:
public interface Generator {
String generate() throws IOException;
}
And in an other lib:
public interface GeneratorInterface {
String generate();
}
If I write a Class with a generate method without any CheckedException I can easily use this to satisfy both Interfaces and maybe work with both libs:
public class EmptyStringGenerator implements Generator,GeneratorInterface {
#Override
public String generate() {
return "";
}
}
Also as far as I know Java is the only language with such handling of Checked and Unchecked exceptions and so the design decisions which pull through Java are strange compared with other languages not having Checked exceptions.

Java interface extends questions

I have to implement an RMI server which will be a front end for two other RMI services. So I decided a logical thing to do would be to have the interface for this implement the interfaces for the other two services.
public interface FrontEndServer extends Remote, BookServer, StudentServer
{
// Block empty so far
}
However there is a method on the StudentServer
/**
* Allows a student to borrow a book
*
* #param studentID of the student who wishes to borrow a book
* #param bookID of the book the student wishes to borrow
* #throws RemoteException
* #throws StudentNotFoundException when a student is not found in the system
*/
void addBookToStudent(int studentID, int bookID) throws RemoteException, StudentNotFoundException;
I would like the FrontEndServer to also throw a BookNotFoundException as this service will also validate if the book actually exists before attempting to add the details in.
Is this possible or is my design idea completely off and this is actually a bad design idea as if the other interfaces change and all? And will I be better of writing the method signatures for all the methods inside the FrontEndServer?
If you extend an interface (the same applies if you implement an interface), you can't override a method and have it throw more checked exceptions than the original. You can it throw the same or less but not more.
Think about it:
interface A {
void foo();
}
interface B extends A {
void foo() throws IOException;
}
A a = new B() { ... }
a.foo();
would potentially throw an IOException but you'd have no way of knowing. That's why you can't do it.
This of course is perfectly acceptable:
interface A {
void foo() throws IOException;
}
interface B extends A {
void foo();
}
A a = new B() { ... }
try {
a.foo();
} catch (IOException e) {
// must catch even though B.foo() won't throw one
}
Your BookNotFoundException could however extend RuntimeException or RemoteException. Not sure that's a good approach however.
What good does a single type that extends both of these interfaces? Do you lose anything when a client depends on two distinct objects?
Overuse of inheritance is a common beginner mistake, because "inheritance" is one of the notable traits of object-oriented programming. However, in most cases, composition is a better choice. In this case, why not have two separate services? Then, adding CafeteriaService and DormitoryService later doesn't impact any existing interfaces.
With regard to the design, the addBookToStudent method would benefit from being able to throw BookNotFoundException. Interfaces are brittle, in the sense that changing them in any way breaks a lot of code. You have to be very careful in their initial design. For example, BookNotFoundException is probably to specific; couldn't there exist a variety of exceptions that would prevent "adding" a book to a student? (I'm guessing that students are checking books out of a lending library.) For example: CheckOutLimitExceededException, UnpaidFinePendingException, AdultLiteraturePermissionException, etc.
Think carefully about the types of checked-exceptions that might be appropriate for the level of abstraction when designing interfaces, because they are hard to change later.
A few ideas for you:
Declare the addBookToStudent method in the interface to throw a BookNotFoundException. Even though the StudentServer might never actually throw the exception, that doesn't mean you can't put it in the interface anyways.
You could create a new exception - ObjectNotFoundException and have BookNotFoundException and StudentNotFoundException inherit from there, then declare addBookToStudent to throw an ObjectNotFoundException.
What I would probably do in "real life" - have the StudentServer talk to the BookServer to validate the book id and throw the exception itself, rather than doing that check in the FrontEndServer. Especially if the StudentServer would actually be used directly by anything other than the FrontEndServer.
I would suggest you attempt to separate your exposed API from the API's used to implement your functionality. My guess is that the purpose of front ending of the RMI services is to provide seperation and stability from the calling application.
With that I would suggest that you:
Write the API you want to expose
Write implementations that bridge between your API and back-end services
It is theoretically possible if BookNotFoundException extends RemoteExcepiton.
However, I assume that you do not have control over the StudentServer interface. It appears that the intent of that interface is to not throw a BookNotFoundException. While I can understand why you want to, the interface doesn't seem to encourage that.
Exceptions are thrown by methods not interfaces or classes. So if there is a method in the BookServer interface it could throw you exception when you add it to the interface.
If you are thinking of adding the exception to the addBookToStudent method in the FrontEndServer interface, the answer is no it is not possible. Overridden methods in classes and interfaces may only narrow the exception or remove it completely but not add new exceptions.
If you think about it, you see that this is logical. Your FrontEndServer could be used as a BookServer by some code. The code during compilation expects the exceptions defined in the BookServer. Then during runtime suddenly an exception is throw by the BookServer that is not defined in the BookServer interface. If that piece of code only knows the BookException is unexpected, there are no catches or throws statements to deal with it.

Categories

Resources