Sunday, July 20, 2008

SCJP6 Mock Exam Questions: Exception Handling, Polymorphism and Inheritance

Given the following code, which of the following methods could be defined in the SunCertified class without causing a compile error?

public class Certified {

public void getCertified() throws GreatGrandChildException { }
}

class SunCertified extends Certified {
}

class ChildException extends Exception{}
class GrandChildException extends ChildException{}
class GreatGrandChildException extends GrandChildException {}


a) public void getCertified() throws Exception { }
b) public void getCertified() throws ChildException { }
c) public void getCertified() throws GrandChildException { }
d) public void getCertified() throws GreatGrandChildException { }

Option d) is correct.

An important rule in Java says that when you override a method in a subclass, you cannot throw any checked Exceptions other than those declared in the method you are overriding. So, since the parent, Certified class does not indicate any checked exceptions in the getCertified() method's throws clause, the overriding method in the SunCertified class is not allowed to throw any new Exceptions either.

Trying to override a method in a subclass, and subsequently throwing a new type of exception in the overriding method, will generate a compiler error such as this one:

C:\_jdk1.6\bin>javac Certified.java
Certified.java:9: getCertified() in SunCertified cannot override getCertified()
in Certified; overridden method does not throw java.lang.Exception
public void getCertified() throws Exception { }
^
1 error


###############################

Given the following code, which of the following methods could be defined in the SunCertified class without causing a compile error?

public class Certified {

public void getCertified() throws ChildException { }
}

class SunCertified extends Certified {
}

class ChildException extends Exception{}
class GrandChildException extends ChildException{}
class GreatGrandChildException extends GrandChildException {}


a) public void getCertified() throws Exception { }
b) public void getCertified() throws ChildException { }
c) public void getCertified() throws GrandChildException { }
d) public void getCertified() throws GreatGrandChildException { }

Options b) c) and d) are correct.

When a subclass overrides a method defined in a parent class, it cannot throw any checked exceptions that are not explicitly thrown by the method being overridden from the ancestor or parent class. However, polymorphism in Java dictates that whenever a certain instance of a class is needed, required or defined, any instance of a subclass can take its place. So, while the parent class, Certified, only throws the ChildException in its getCertified method, any overriding getCertified() method in a subclass is more than welcome to throw a more specific, subclass of the ChildException that is thrown in the ancestor class.

Polymorphism in Java indicates that any time a particular class is needed, and instance of that class, or instance of a subclass that wil share an is-a relationship with that requested class, will do.

##################################################

Given the following code, which of the following methods could be defined in the SunCertified class without causing a compile error?

public class Certified {
public void getCertified() throws ChildException { }
}

class SunCertified extends Certified {}

class ChildException extends Exception{}
class GrandChildException extends ChildException{}
class GreatGrandChildException extends GrandChildException {}


a) public void getCertified() throws Exception, ClassCastException { }
b) public void getCertified() throws ChildException, IllegalStateException { }
c) public void getCertified() throws GrandChildException, IllegalStateException { }
d) public void getCertified() throws GreatGrandChildException, NoClassDefFoundError { }


Options b) c) and d) are correct.

Since the getCertified() method in the ancestor class, Certified, throws java.lang.ChildException, any subclass overriding the getCertified() method must also throw an instance of the ChildException if it is to have a throws clause. Since GreandChildException and GreatGrandChildException are both subclasses of ChildException, they share an is-a relationship with the ChildException class, and as such, they are allowed in the throws clause of the method named getCertified().

However, you will notice that the getCertified() methods in options a) b) c) and d) all throw unchecked, runtime exceptions, that were not thrown in the method definition of the parent class. This is okay, as an overriding method can mention any number of unchecked, runtime exceptions that may or may not have been defined in the method being overridden from the parent class.

When it comes to throwing exceptions in overridden methods, you cannot throw any checked exceptions that don't share an is-a relationship with the exception thrown in the corresponding method defined in the parent class. However, this rule does not apply to unchecked, runtime exceptions, so an overridden method can throw any number of unchecked exceptions, regardless of whether they were defined by the method being overridden from the parent class or not.

The RuntimeException classes that are explicitly defined by the SCJP 6 exam objectives include:
ArrayIndexOutOfBoundsException, ClassCastException, IllegalArgumentException, IllegalStateException, NullPointerException, NumberFormatException, AssertionError, ExceptionInInitializerError, StackOverflowError and NoClassDefFoundError.




#######################################################

Given the following code, which of the following methods could be defined in the SunCertified class without causing a compile error?

public class Certified {

public void getCertified() throws GreatGrandChildException { }

}

class SunCertified extends Certified {

}

class ChildException extends Exception{}
class GrandChildException extends ChildException{}
class GreatGrandChildException extends GrandChildException {}

a) public void getCertified() { }
b) public void getCertified() throws ClassCastException { }
c) public void getCertified() throws ChildException, IllegalStateException { }
d) public void getCertified() throws GrandChildException, IllegalStateException { }
e) public void getCertified() throws GreatGrandChildException, NoClassDefFoundError { }


Options a) b) and e) are correct.

When you override a method that has a throws clause, it is completely valid for your overridden implementation of that method not to have a throws clause at all, making option a) correct.

Furthermore, an overridding method is allowed to throw any number of unchecked, RuntimeException or Error objects, regardless of whether the RuntimeException or Error object was thrown in the inherited method that is being overridden, making option b) completely valid.

Options c) and d) will not compile, as the overriding method tries to throw exceptions that are less specific than the one thrown by the getCertified() method in the parent class. ChildException and GrandChildException do not share an is-a relationship with the GreatGrandChildException, and as a result, throwing them in the overridding method generates a compile error.

Option e) will indeed compile, as both the overridding method and the overridden method both throw the exact same checked exception, the GreatGrandChildException. The overridden method also throws the NoClassDefFoundError, but overriding methods can throw any number of Errors that are not explicilty defined in the method being overridden, so this does not cause a problem when using option e).

###########################################

The following code does not compile. How should the getCertified() method be refactored to allow this code to compile?

public class Certified {


getCertified {

String input = (new java.util.Scanner( System.in )).nextLine();

if (input.equals("SCJA")) { throw new ChildException(); }
if (input.equals("SCJP")) { throw new RuntimeException(); }
if (input.equals("SCEA")) { throw new Error(); }

}
}

class ChildException extends Exception {}
class GrandChildException extends ChildException{}
class GreatGrandChildException extends GrandChildException {}

a) public static void getCertified()
b) public static void getCertified() throws Error, RuntimeException
c) public static void getCertified() throws Exception, Error
d) public static void getCertified() throws ChildException
e) public static void getCertified() throws RuntimeException, Error, GrandChildException

Options c) d) and are correct.

Any method that might throw a checked exception must state so explicitly in the throws clause of the method. Since ChildException is a checked exception, the ChildException, or any throwable parent of the ChildException, must be mentioned in the getCertified() method's throws clause. This makes options c) and d) correct.

Option a) is incorrect, as it does not mention the fact that the ChildException might be thrown when this method runs. This is the same reason that options b) and e) are incorrect as well. Option e) mentions that GrandChildException might be thrown, but this Exception is more specific, and below ChildException on the class hierarchy, meaning that handling the GrandChildException would not necessarily provide proper handling for situations where the parent, ChildException, might be thrown.

One thing to note is that while the getCertified() method may throw a checked Exception, an unchecked RuntimeException, or even an instance of an Error, only the checked Exception is absolutely required to be specified in the throws clause of the method.

No comments: