Try-catch problem with inheritance (Java) - java

We're trying to implement some sort of Chess game and we have defined an abstract class Piece with constructor:
public Piece(String name) throws EmptyStringException{
if(name.length()<=0)
throw new EmptyStringException();
pieceName = name;
}
And an extending class could look like this:
public King(boolean white) throws EmptyStringException{
super("King", white);
}
The 'problem' here is, if i want to create a new King piece i have to write:
try {
Piece king = new King(true);
} catch(EmptyStringException e){
e.printStackTrace();
}
instead of the much simpler:
Piece king = new King(true);
So even though i simply can't create an EmptyStringException, i still have to try/catch the exception.
How can i solve this so i can still throw the EmptyStringException in Piece, but don't have to try/catch every time i need to create a new chesspiece ?

Use runtime exception:
public class EmptyStringException extends RuntimeException
instead of plain Exception. You can still document your exception in method declaration, but you are not forcing client code to deal with the exception.

Make EmptyStringException extend RuntimeException. The compile won't complain about any RuntimeExceptions thrown in a method that are missing in the throws clause.
Note that you can even include the exception in the throws clause to document that you throw it. Except for documentation purposes, this has no effect.
You should only use checked exceptions (which are derived directly from java.lang.Exception) for exceptions that the caller should handle. You should not use them for things that "can happen" like:
Out of memory
Argument errors
IO exceptions (which the Java RT got wrong and now serves as a perfect "how not do it" example)

Since you cannot catch exceptions from parent constructors, I'd follow the other provided suggestions and make your exception a RuntimeException, or use the existing exception IllegalArgumentException.
If you were in a situation where you couldn't modify the base class or change the exception being thrown and factory method could work.
public class King {
private King() {
super("King");
}
public King createInstance() {
try {
new King();
} catch (EmptyStringException e) {
throw new RuntimeException("Unexpected expection thrown", e);
}
}
}
But in your case just having Piece throw a RuntimeException is a cleaner solution.
Also if Piece's constructor is only going to be called by subclasses, consider making it protected and using assert statements to detect an empty name.
Edited - Removed incorrect advice

So even though i simply can't create an EmptyStringException, i still have to try/catch the exception.
What do you mean? Your Piece constructor is declared as throws EmptyStringException. So as far as the compiler is concerned, it can throw an EmptyStringException, simply because you've told it so.

As has been said, use a RuntimeException.
But I will add that it should be IllegalArgumentException instead of your custom one. There is no need to create your own application specific exceptions when existing standard ones exist.
Java, Class-specific Exceptions vs. Standard Exceptions

I'm reluctant to use RuntimeExceptions because this short-circuits the built-in enforcement that all excetions be handled somewhere. Yes, on your King object the exception should never happen, it's an internal coding error, so a RuntimeException is arguably appropriate. But this is clearly not the case on your Piece object.
Java's annoying rule that the super() must be the first statement prevents you from trapping the error in the King constructor.
The alternative I've used in some programs has been to move all the constructor code to an ordinary function, and then have the constructor call this function. Like:
public class Piece
{
public Piece(String name) throws EmptyStringException
{
initPiece(name);
}
// Protect so outsiders must use legal constructors
protected Piece()
{
// nop
}
protected void initPiece(String name) throws EmptyStringException
{
if (name.length()==0)
throw new EmptyStringException();
pieceName=name;
}
}
public class King extends Piece
{
public King(boolean white)
{
try
{
initPiece("King");
}
catch (EmptyStringException panic)
{
throw new RuntimeException(panic.toString()); // should never happen
}
}
}
In other words, avoid the need to call super. Call something else to do the initialization. Then the special rules about super don't apply.
Another option is to create a factory method for King rather than a constructor. Say:
public class Piece
{
public Piece(String name) throws EmptyStringException
{
if (name.length()==0)
throw new EmptyStringException();
pieceName=name;
}
public Piece makeKing(boolean white)
{
try
{
return new Piece("King");
}
catch (EmptyStringException e)
{
throw new RuntimeException(e.toString()); // won't ever happen
}
}
}
If King really needs to be its own class, you could still do that above, it's the same concept.

Related

Advantage of declaring an exception

If I have a class called Boat, and if I write :
class Boat throws Exception
Inside my class I am using try catch block to catch ArithmeticException for instance.
What benefit there is to declare an exception versus not declaring an exception?
A class does not throw exceptions. Only methods do.
For some exceptions (checked exceptions that may occur in your code and that you do not catch) the compiler forces you to declare them.
You never have to declare RuntimeExceptions (such as ArithmeticException), but you can. This serves as documentation.
You can declare checked exceptions that your code does not throw. This makes it future-proof if you might later want to throw them, and also allows for subclasses to do such.
When declaring exceptions, you can go broad/generic (throws Exception or even throws Throwable), but it is generally better to be more specific. That gives the people using your code a better idea of what to expect. The whole purpose of having these many specific Exception classes is to make it easier to handle exceptions appropriately (and have the compiler enforce the fact that someone at least thought about doing that).
First classes won't throw Exception, only methods will throw
check this Example
class A
{
public A() throws Exception
{
int k=5/0;
}
}
public class B
{
public static void main(String[] args)
{
A a=new A();
}
}
When you run the above you'll get compile time error saying
Unhandled exception type Exception
because when ever methods throws exception , they are expected to handle by calling object, it is just like saying 'Hey somebody handle Exception', so the method calling it should handle the Exception , if they don't it will be a compile time error.
For the smooth execution of program, Exception thrown by method should be handle by calling method. Here is how you need to handle.
class A
{
public A() throws Exception
{
int k=5/0;
}
}
public class B
{
public static void main(String[] args)
{
try{
A a=new A();
}
catch(Exception e)
{
System.out.println("caught "+e);
}
}
}
Declaring Exception will allow your program to compile if any Exception can be determined by the compiler to "escape". It's primary purpose, though, is to document to the user of your method (and to their compilers) that it may throw an Exception.
As such, declaring Exception, vs declaring a more specific exception cause, is nullifying the benefits of the scheme -- cheating.
If you write something like that,
double x = 1/0;
System.out.print("hey");
it will give you an exception and your code is going to stop, will not print hey. But if you encapsulate it with try/catch, it will not stop.
try{
double x = 1/0;
}catch(ArithmeticException){}
System.out.print("hey");
This will print hey.

java : how to handle the design when template methods throw exception when overrided method not throw

when coding. try to solve the puzzle:
how to design the class/methods when InputStreamDigestComputor throw IOException?
It seems we can't use this degisn structure due to the template method throw exception but overrided method not throw it. but if change the overrided method to throw it, will cause other subclass both throw it.
So can any good suggestion for this case?
abstract class DigestComputor{
String compute(DigestAlgorithm algorithm){
MessageDigest instance;
try {
instance = MessageDigest.getInstance(algorithm.toString());
updateMessageDigest(instance);
return hex(instance.digest());
} catch (NoSuchAlgorithmException e) {
LOG.error(e.getMessage(), e);
throw new UnsupportedOperationException(e.getMessage(), e);
}
}
abstract void updateMessageDigest(MessageDigest instance);
}
class ByteBufferDigestComputor extends DigestComputor{
private final ByteBuffer byteBuffer;
public ByteBufferDigestComputor(ByteBuffer byteBuffer) {
super();
this.byteBuffer = byteBuffer;
}
#Override
void updateMessageDigest(MessageDigest instance) {
instance.update(byteBuffer);
}
}
class InputStreamDigestComputor extends DigestComputor{
// this place has error. due to exception. if I change the overrided method to throw it. evey caller will handle the exception. but
#Override
void updateMessageDigest(MessageDigest instance) {
throw new IOException();
}
}
In this case, your super class is not meant to throw an exception.
This is a case where your subclass is thus throwing an exception which is not expected by the overlying software architecture. Thus you can :
update all subclasses to throw exceptions.
wrap the entire Digestor class framework in a new class system.
(simplest) maintain the current code and simply wrap any exceptions you wish to throw in a RuntimeException.
RuntimeExceptions are the idiomatic way to throw exceptions in java which are not checked by the compiler or by method signatures, which occur somewhat unexpectedly.
Your requirements are schizophrenic.
You've got to decide whether the DigestComputor.updateMessageDigest method can, or can not throw IOException. If you want that to be possible, then you must add it to the signature in the base class. That is the only way to force the caller to do something about an IOException. But the downside is that you also force callers of the other subclasses to handle the IOException ... which won't occur.
You cannot create a method override that throws checked exceptions that the overridden method does not. That would break subtype substitutability, and Java doesn't allow it.
It it like a fork in the road. You have to decide to go one way or the other. You can't go both ways at the same time.
However there is a compromise (sort of):
public abstract class Base {
public abstract void method() throws IOException;
}
public class A extends Base {
public void method() throws IOException {
//
}
}
public class B extends Base {
public void method() { // Doesn't throw!!!
//
}
}
Now, if the caller knows that it has an instance of B it can do something like this:
Base base = ...
B b = (B) base;
b.method(); // No need to catch or propagate IOException
(IIRC, the ability to do this ... i.e. to reduce the exceptions thrown in an overriding method ... was added in Java 1.5.)
As someone else suggested, the simplest thing to do would be to simple wrap the real exception in a runtime exception. As a result, you don't have to declare the exception in your throws clause. If you're ambitious enough you can make your own subclass of RuntimeException and catch it at a higher level (this is what hibernate does, it catches all SQLExceptions thrown and wraps them in some subclass of DataAccessException which is a runtime exception).

What to put in the throws clause of an interface method?

Suppose I have interface I and two classes A and B that implement it.
The implementation of method f of this interface in A throws one set of exceptions and the implementation in B throws another set. The only common ancestor of these exceptions is java.lang.Exception. Is it reasonable to declare f throwing java.lang.Exception in this case? Any other alternatives?
The reason why I am asking is that on the one hand java.lang.Exception seems too general to me and one the other hand listing all exceptions seems impractical considering possible other implementations.
Example:
interface I {
void f() throws Exception;
}
class A implements I {
public void f() throws IOException {}
}
class B implements I {
public void f() throws InterruptedException {}
}
The reason for using an interface is to abstract away the implementation details.
By throwing these exceptions, you're exposing implementation details that probably should be abstracted away.
Perhaps it would be best to define a new exception. Then each implementation of f() would catch the exceptions it knows about and throw the new exception instead so you'd have:
interface I {
void f() throws MyException;
}
class A implements I {
public void f() throws MyException {
try {
...
} catch (IOException e) {
throw new MyException(e);
}
}
}
class B implements I {
public void f() throws MyException {
try {
...
} catch (InterruptedException e) {
throw new MyException(e);
}
}
}
By wrapping the implementation exception, you're still exposing it to the caller and that can bite you when you're calling remote methods. In those cases you need to do more work to return useful information in a generic way.
Edit
There seems to be a bit of a dispute going on about the correct approach.
When we call f(), we'll need code like:
I instanceOfI = getI();
try {
instanceOfI.f();
}
catch ( /* What should go here ? */ )
It comes down to what is a good Exception class to put in the catch block.
With OP's original code we could catch Exception and then maybe try to see which subclass we have, or not depending on requirements. Or we could individually catch each subclass but then we'd have to add catch blocks when new implementations throw different exceptions.
If we used Runtime exceptions it would come to much the same thing except that we could alternatively defer the exception handling to a caller method without even giving the possibility of exceptions any thought.
If we used my suggestion of using a new, wrapped exception then this means we have to catch MyException and then try to see what additional information is available. This essentially becomes very like just using an Exception, but requires extra work for the limited benefit of having a bespoke exception that can be tailored to the purpose.
This seems a bit backward. You should be throwing exceptions that are relevant and possibly specific to your interface, or not at all. Change the implementations to wrap a common Exception class (although not Exception itself). If you can't deal with this you may want to wrap the Exceptions in the implementations with a RuntimeException.
You could just declare the exceptions you throw
void f() throws IOException, InterruptedException;
If you use a decent IDE, it will correct this for you. I just throw the exception in the method, which the IDE gives the optionsto add to the method clause and its interface.

What is the preferred Throwable to use in a private utility class constructor?

Effective Java (Second Edition), Item 4, discusses using private constructors to enforce noninstantiability. Here's the code sample from the book:
public final class UtilityClass {
private UtilityClass() {
throw new AssertionError();
}
}
However, AssertionError doesn't seem like the right thing to throw. Nothing is being "asserted", which is how the API defines the use of AssertionError.
Is there a different Throwable that's typically in this situation? Does one usually just throw a general Exception with a message? Or is it common to write a custom Exception for this?
It's pretty trivial, but more than anything I guess I'm just curious about it from a style and standards perspective.
There is an assertion: "I'm asserting that this constructor will never be called". So, indeed, AssertionError is correct here.
I like including Bloch's comment:
// Suppress default constructor for noninstantiability
Or better yet putting it in the Error:
private UtilityClass()
{
throw new AssertionError("Suppress default constructor for noninstantiability");
}
UnsupportedOperationException sounds like the best fit, though a checked exception would be even better, since it might warn someone erroneously instantiating the class at compile time.
What about IllegalAcessError ? :)
When the code requires the inclusion of the JUnit as a dependency such as within the maven test scope <scope>test</scope>, then go straight to Assertion.fail() method and benefit from significant improvement in clarity.
public final class UtilityClass {
private UtilityClass() {
fail("The UtilityClass methods should be accessed statically");
}
}
When outside the test scope, you could use something like the following, which would require a static import to use like above. import static pkg.Error.fail;
public class Error {
private static final Logger LOG = LoggerFactory.getLogger(Error.class);
public static void fail(final String message) {
LOG.error(message);
throw new AssertionError(message);
// or use your preferred exception
// e.g InstantiationException
}
}
Which the following usage.
public class UtilityClassTwo {
private UtilityClassTwo() {
Error.fail("The UtilityClass methods should be accessed statically");
}
}
In its most idiomatic form, they all boil down to this:
public class UtilityClassThree {
private UtilityClassThree() {
assert false : "The UtilityClass methods should be accessed statically";
}
}
One of the built in exceptions, UnsupportedOperationException can be thrown to
indicate that 'the requested operation is not supported'.
private Constructor() {
throw new UnsupportedOperationException(
"Do not instantiate this class, use statically.");
}
No no no, with all due respect to Josh Bloch, never throw an AssertionError unless it's from an assertion. If you want an AssertionError here, throw it with assert(false). Then someone reading the code can find it later.
Even better, define your own exception, say CantInstantiateUtilityClass. then you'll have code that says
try {
// some stuff
} catch (CantInstantiateUtilityClass e) {
// react
}
so that the reader of the catcher knows what happened.
Let me just note that the standard still defines AssertionError as the result of a failed assertion, not as what some beginner thinks ought to be thrown in place of a well-defined informative exception. Sadly, good exception discipline is perhaps the least encouraged skill in Java programming.
A broken assertion means that you've broken a contract specification of your code. So it's the right thing here.
However, as I assume you'll be privately instantiating an instance, it will also call the constructor and cause an error- unless you have another constructor?
You can create your own class extending Throwable, e.g.:
class NoninstantiabilityError extends Throwable
This has the following advantages:
The name indicates the problem
Because it directly extends Throwable it is unlikely that it will be caught by accident
Because it directly extends Throwable it is checked and calling the respective constructor by accident would require catching the exception
Usage example:
public final class UtilityClass {
private UtilityClass() throws NoninstantiabilityError {
throw new NoninstantiabilityError();
}
...
}

Why can't I use a try block around my super() call?

So, in Java, the first line of your constructor HAS to be a call to super... be it implicitly calling super(), or explicitly calling another constructor. What I want to know is, why can't I put a try block around that?
My specific case is that I have a mock class for a test. There is no default constructor, but I want one to make the tests simpler to read. I also want to wrap the exceptions thrown from the constructor into a RuntimeException.
So, what I want to do is effectively this:
public class MyClassMock extends MyClass {
public MyClassMock() {
try {
super(0);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// Mocked methods
}
But Java complains that super isn't the first statement.
My workaround:
public class MyClassMock extends MyClass {
public static MyClassMock construct() {
try {
return new MyClassMock();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public MyClassMock() throws Exception {
super(0);
}
// Mocked methods
}
Is this the best workaround? Why doesn't Java let me do the former?
My best guess as to the "why" is that Java doesn't want to let me have a constructed object in a potentially inconsistent state... however, in doing a mock, I don't care about that. It seems I should be able to do the above... or at least I know that the above is safe for my case... or seems as though it should be anyways.
I am overriding any methods I use from the tested class, so there is no risk that I am using uninitialized variables.
Unfortunately, compilers can't work on theoretical principles, and even though you may know that it is safe in your case, if they allowed it, it would have to be safe for all cases.
In other words, the compiler isn't stopping just you, it's stopping everyone, including all those that don't know that it is unsafe and needs special handling. There are probably other reasons for this as well, as all languages usually have ways to do unsafe things if one knows how to deal with them.
In C# .NET there are similar provisions, and the only way to declare a constructor that calls a base constructor is this:
public ClassName(...) : base(...)
in doing so, the base constructor will be called before the body of the constructor, and you cannot change this order.
It's done to prevent someone from creating a new SecurityManager object from untrusted code.
public class Evil : SecurityManager {
Evil()
{
try {
super();
} catch { Throwable t }
{
}
}
}
I know this is an old question, but I liked it, and as such, I decided to give it an answer of my own. Perhaps my understanding of why this cannot be done will contribute to the discussion and to future readers of your interesting question.
Let me start with an example of failing object construction.
Let's define a class A, such that:
class A {
private String a = "A";
public A() throws Exception {
throw new Exception();
}
}
Now, let's assume we would like to create an object of type A in a try...catch block.
A a = null;
try{
a = new A();
}catch(Exception e) {
//...
}
System.out.println(a);
Evidently, the output of this code will be: null.
Why Java does not return a partially constructed version of A? After all, by the point the constructor fails, the object's name field has already been initialized, right?
Well, Java can't return a partially constructed version of A because the object was not successfully built. The object is in a inconsistent state, and it is therefore discarded by Java. Your variable A is not even initialized, it is kept as null.
Now, as you know, to fully build a new object, all its super classes must be initialized first. If one of the super classes failed to execute, what would be the final state of the object? It is impossible to determine that.
Look at this more elaborate example
class A {
private final int a;
public A() throws Exception {
a = 10;
}
}
class B extends A {
private final int b;
public B() throws Exception {
methodThatThrowsException();
b = 20;
}
}
class C extends B {
public C() throws Exception { super(); }
}
When the constructor of C is invoked, if an exception occurs while initializing B, what would be the value of the final int variable b?
As such, the object C cannot be created, it is bogus, it is trash, it is not fully initialized.
For me, this explains why your code is illegal.
I can't presume to have a deep understanding of Java internals, but it is my understanding that, when a compiler needs to instantiate a derived class, it has to first create the base (and its base before that(...)) and then slap on the extensions made in the subclass.
So it is not even the danger of uninited variables or anything like that at all. When you try to do something in the subclass' constructor before the base class' constructor, you are basically asking the compiler to extend a base object instance that doesn't exist yet.
Edit:In your case, MyClass becomes the base object, and MyClassMock is a subclass.
I don't know how Java is implemented internally, but if the constructor of the superclass throws an exception, then there isn't a instance of the class you extend. It would be impossible to call the toString() or equals() methods, for example, since they are inherited in most cases.
Java may allow a try/catch around the super() call in the constructor if 1. you override ALL methods from the superclasses, and 2. you don't use the super.XXX() clause, but that all sounds too complicated to me.
I know this question has numerous answers, but I'd like to give my little tidbit on why this wouldn't be allowed, specifically to answer why Java does not allow you to do this. So here you go...
Now, keep in mind that super() has to be called before anything else in a subclass's constructor, so, if you did use try and catch blocks around your super() call, the blocks would have to look like this:
try {
super();
...
} catch (Exception e) {
super(); //This line will throw the same error...
...
}
If super() fails in the try block, it HAS to be executed first in the catch block, so that super runs before anything in your subclass`s constructor. This leaves you with the same problem you had at the beginning: if an exception is thrown, it isn't caught. (In this case it just gets thrown again in the catch block.)
Now, the above code is in no way allowed by Java either. This code may execute half of the first super call, and then call it again, which could cause some problems with some super classes.
Now, the reason that Java doesn't let you throw an exception instead of calling super() is because the exception could be caught somewhere else, and the program would continue without calling super() on your subclass object, and possibly because the exception could take your object as a parameter and try to change the value of inherited instance variables, which would not yet have been initialized.
One way to get around it is by calling a private static function. The try-catch can then be placed in the function body.
public class Test {
public Test() {
this(Test.getObjectThatMightThrowException());
}
public Test(Object o) {
//...
}
private static final Object getObjectThatMightThrowException() {
try {
return new ObjectThatMightThrowAnException();
} catch(RuntimeException rtx) {
throw new RuntimeException("It threw an exception!!!", rtx);
}
}
}

Categories