Widening exception of overridden method in Java - java

Assume we have two classes:
Class A:
import java.io.IOException;
public class A {
public void test() throws IOException{
System.out.println("test in A");
}
}
Class B:
import java.io.IOException;
public class B extends A {
#Override
public void test() throws Exception{
System.out.println("test in B");
}
}
This gives a compiler error, and I would like to know the reason for it. I can get the answer by myself, but this is not fully scientific, but partly logically.
I wrote a blog post in Azerbaijani. When I wrote the blog I was stuck in the loading process.
Please be careful in quotes:
I think that when the compiler reads the B class, it loads the method headers of A and method headers of B. And when you call test of A, the JVM calls the test of A, but as body calls test of B, and at that time we will have this method:
public void test() throws IOException{ // <-- Header of A
System.out.println("test in B"); // <-- Body of B
// Here I can throw wide Exception from IOException
// because here is the body of the test in B. The test
// method in B can throw Exception so the compiler
// doesn't approve of this version of the code.
}
Is the process really going on as what I wrote above?
Loading headers issue I was stuck exactly here.
How does the linking process work? I can't figure out background of
A a = new B(); // When the compiler converts this line into bytecode
// does it loads of method headers of A and method
// body's of B
a.test()
calls the test of the B class. I know logically, but I can't figure out at the compiler level, linking process.

Imaigine you have the following code:
A a = new B();
try {
a.test();
} catch (IOExceoption e) {
//do some specific handle for IOExceoption
}
Now imaigine what happens if b.test() throw an Exception which is NOT IOException? nobody will handle it, and that breaks java's checked exceptions mechanism.
The other way around however, is perfectly fine:
public class A {
public void test() throws Exception {
System.out.println("test in A");
}
}
public class B extends A {
#Override
public void test() throws IOException{
System.out.println("test in B");
}
}
A a = new B();
try {
a.test();
} catch (Exception e) {
//handle
}
Now, note that the catch handles a general Exception, including the specific IOException, and the code will compile perfectly.

The overidden method can throw anything which is an IOException your case. Or more generally, it can throw any exception that is a ParentException. So, you can throw FileNotFoundException since it is also an IOException.
Why?
Not adhereing to this rule breaks the primary contract between parent-child in inheritance.
Somewhere else in your code you can safely assume that the exception thrown from the call to test() will always be IOException irrespective of Which implementation of A threw it. If you were allowed to throw InterruptedException in your case, what exception should the caller catch?
The compiler doesn't load anything. It just marks the method as invoke virtual which means this method is overriden and supposed to be called at run-time based on the object type

From a bit different angle, you are basically not overriding existing method in super type.
Exceptions which are thrown are part of the method's signature.
When you declare your test method in class B with override annotation, you are in fact trying to override (or implement) method which does not exist in its parent A.

Related

Can I define multiple custom exceptions in java in a single class file and invoke them via methods?

I'm trying to get into exception handling via custom exceptions.
I'm creating the class CustomExceptions and extending Exception as follows:
public class CustomExceptions extends Exception{
public CustomExceptions (String s) {
super(s);
}
However, rather than having to create multiple files for every custom exception I want, or bloating my main class file, I'd like to put all of my custom exceptions in this class and invoke them via a method
So let's say that I want to handle 2 situations: When the user tries to input a seat reservation, but the seat is already taken, and when the user tries to provide a ticket for someone outside of the age range.
Can I create 2 methods inside of the CustomExceptions class which invoke the constructor passing a custom message to it?
public void seatTaken(String s) {
String s = "The seat is taken, please choose a new one";
CustomExceptions(s);
}
public void notOldEnough(String s) {
String s = "User is not old enough for this movie.";
CustomExceptions(s)
}
}
Would this work? Or am I forced to create multiple custom exception files?
Generally custom exceptions should be defined in the top level. Because, almost universally, these exceptions are part of the interface of the package or module.
If the user cannot see them, then how are they going to catch them separately? And if you don't want to catch them separately, then why would you need separate classes?
However, if you must, you can include them into a class for which they are required:
public class SeatReservationSystem {
public static class ReservationFailedException {
... constructors taking a message ...
}
public static class SeatTakenException extends ReservationFailedException {
... constructors taking a message ...
}
public static class OutsideAgeException extends ReservationFailedException {
... constructors taking a message ...
}
....
}
After that you can create any method that returns them as required. Don't create methods that throw them as the compiler won't see those as exit points of the block you're in, and you'll get strange situations.
Here is some code to show what I mean:
// wrong
public static void throwRuntimeException() throws RuntimeException {
throw new RuntimeException();
}
// correct, but dangerous
public static RuntimeException createRuntimeException() {
return new RuntimeException();
}
public static void main(String[] args) {
String initializeMeOrThrowException;
if (new Random().nextBoolean()) {
// compiler doesn't recognize that the method always throws an exception
throwRuntimeException();
// this the compiler can understand, there is an explicit throw here:
// throw createRuntimeException();
// but this is the pitfall, it doesn't do anything:
// createRuntimeException();
} else {
initializeMeOrThrowException = "Initialized!";
}
// Compiler error for throwRuntimeException and createRuntimeException without throws:
// "The local variable initializeMeOrThrowException may not have been initialized"
System.out.println(initializeMeOrThrowException);
}
However, experience learns me that I forget the throws statement for the throw createException(...); method, and the stupid compiler doesn't warn me about that (even though the statement is utterly useless without it). So I try and not use either.
Note that I'm not certain if you should use exceptions for this. If your system is a reservation system, then refusing tickets is not that exceptional. Returning a ReservationResult makes more sense.

super class constructor in custom exception in java

I am learning features in java including exceptions. I am writing a custom exceptions. Here is what i am doing :custom exception class:
public class ServiceException extends Exception {
private String customMessage;
public ServiceException(String customMessage) {
super(customMessage);
this.customMessage = customMessage;
}
}
Main class:
public class Main {
public static void main(String[] args) {
try {
new Main().test();
} catch (Exception e) {
System.out.println("the exception message is " + e.getMessage());
}
}
public void test() throws ServiceException {
try {
int i = 1 / 0;
} catch (Exception e) {
throw new ServiceException(e.getMessage());
}
}
}
This much i know:
if super class constructor is not invoked in the custom exception class, the message set in the custom exception is not passed to the Exception class. But if i have a method public String getMessage in my custom exception class, even if the super is not invoked, that message is printed . Sorry if this is a naive question. But i am failing to understand he concept. Could come one help clear the concept ?
In main where you are catching the error, you are basically assigning a ServiceException object to a Exception reference, i.e. assigning derived class object to base class reference, so if the derived class has overridden the method, it will get called.
the e.message() being called is from ServiceException not Exception, you are right, no data is being passed when you are not calling super, data is inside ServiceException class only and the function invoked is also from ServiceException class.
That is because you are supplying it. You are passing e.getMessage() to your constructor as the only argument, customMessage. You then pass customMessage to its parent's constructor that takes a String, Exception(String). In doing so, you are giving it the message to use for serviceExceptionInstance.getMessage(). Instead, do not pass the customMessage to its parent (use super();, which is implied if no call to a parent constructor is given and a no-arg, parent constructor exists). Then the message will be null as it is not supplied.
In other words:
new ServiceException(e.getMessage());
Creates a new ServiceException with the message from e. You pass that message to Exception, ServiceException's parent.
super(customMessage);
In doing so, you use the single argument, String-based constructor of Exception. Passing a value to that constructor implies that you want it used when callers invoke getMessage. To avoid doing this, call a different parent constructor, or none at all (calling none is technically not possible, and it will implicitly do super(); for you):
public ServiceException(String customMessage)
{
this.customMessage = customMessage;
}
This will call super(); for you, which means that the parent class has no message to send, and by not overriding getMessage() yourself, then it will return its default value (null). To be clear, Exception itself extends from Throwable, which is really the class providing this functionality, but it all stems from how you work with Exception as it serves as a pass-thru to Throwable.

High Level Overview Of Throwing Exceptions In Java

I am a little bit confused with exceptions in Java and when to use which particular style of implementation.
I used IllegalArgumentException as an example, but the main point I would like to address is when does one throw, extends or throw new exception?
Also as an additional point I have an assignment where I have to create a java class and the spec vaguely states that the constructor should throw an IllegalArgumentException so which one would be the best to use?
public class Test{
//when does one use this type of exception
public Test(String yourName) throws IllegalArgumentException{
//code implemented
}
//when does one use this type of exception
public Test(String yourName) extends IllegalArgumentException{
//code implemented
}
public Test(String yourName){
if(yourName.length() <= 0){
//why not use this type of exception instead
//and what happens when I use this type of exception
throw new IllegalArgumentException("Please Enter Your Name..!");
}
}
}
Thanks in advance.
When some Exception occurs, you have two ways of handling it: doing throws from the method or doing try-catch. The first one looks like this:
public class MyClass {
public void myMethod() throws IllegalArgumentException {
someOtherMethod();
}
}
In this case you know that someOtherMethod() can throw an exception and you don't want to handle it - you just pass it further. After that, the invoker of myMethod() should take care of the Exception.
But the second way is when you handle it by yourself:
public void myMethod() {
try {
someOtherMethod();
} catch (Exception e) {
System.out.println("You've got an exception!");
}
}
About throwing exceptions manually - you may suppose that you do it in someOtherMethod(). When you do throw new IllegalArgumentException("Please Enter Your Name..!"); the program stops with a message about this exception (unless you handle it in a try-catch way).
And at last, you extend some exception, when you create your own Exception class:
class MyException extends IllegalArgumentException {
...
}
In this case you may do throw new MyException(); in your code.
I'd advise you to read more about exceptions in Java to understand what is going on. You may start with this lesson.
To ensure that you don't end up creating exceptions which already have equivalent in the standard library, I normally have a peek at the documentation before creating new exceptions. Also, it's very easy to go crazy with really big exception hierarchies if you are not careful. Don't create new exceptions just because you think you need to throw one somehow; create one because a code somewhere down the call stack would be doing something useful/different with that exception.
public Test(String yourName) throws IllegalArgumentException
You normally never specify runtime exception in the throws clause though it might be helpful if you need this information to be part of the public API.
public Test(String yourName) extends IllegalArgumentException
This doesn't look right and isn't valid Java.
I would only create a new exception type when you need to. You need a new type when you expect the caller to have catch clause for your new exception.
you can create new exceptions just to be more descriptive but that is what I use the message for.

Issues trying throw checked exception with mockito

I have the below interface
public interface Interface1 {
Object Execute(String commandToExecute) throws Exception;
}
which then I 'm trying to mock so I can test the behaviour of the class that will call it:
Interface1 interfaceMocked = mock(Interface1.class);
when(interfaceMocked.Execute(anyString())).thenThrow(new Exception());
Interface2 objectToTest = new ClassOfInterface2(interfaceMocked);
retrievePrintersMetaData.Retrieve();
But the compiler tells me that there is an unhandled exception.
The definition of the Retrieve method is:
public List<SomeClass> Retrieve() {
try {
interface1Object.Execute("");
}
catch (Exception exception) {
return new ArrayList<SomeClass>();
}
}
The mockito documentation only shows uses of RuntimeException, and I have not seen anything on similar on StackOverflow.
I'm using Java 1.7u25 and mockito 1.9.5
Assuming your test method doesn't declare that it throws Exception, the compiler's absolutely right. This line:
when(interfaceMocked.Execute(anyString())).thenThrow(new Exception());
... calls Execute on an instance of Interface1. That can throw Exception, so you either need to catch it or declare that your method throws it.
I would personally recommend just declaring that the test method throws Exception. Nothing else will care about that declaration, and you really don't want to catch it.
You can use doAnswer method of Mockito to thrown checked exceptions, like this
Mockito.doAnswer(
invocation -> {
throw new Exception("It's not bad, it's good");
})
.when(interfaceMocked)
.Execute(org.mockito.ArgumentMatchers.anyString());
You shouldn't be having a problem if your method returns something and throws your error. Now if your method returns void you won't be able to throw an error.
Now the real thing is that you're not testing that your interface throws an exception, instead what you're testing what happens when an exception is thrown within this method.
public List<SomeClass> Retrieve() {
try {
interface1Object.Execute("");
}
catch (Exception exception) {
return handleException(exception);
}
}
protected List<SomeClass> handleException(Exception exception) {
return new ArrayList<SomeClass>();
}
Then you just call your handleException method and make sure it returns the correct thing. If you need to make sure that your interface is throwing an exception, then that is a different test for your interface class.
It might seem sucky that you are having to make a method for a single line but that's what happens sometimes if you want testable code.

Java method contains another method throws exception

Inside Method A, there is method B. Method B throws exception, but method A compiled even it does not catch exception or throws exception, could it be possible?
Method B is something like as below:
MethodB() throws SomeException{
if(Some)
doneSomething
return
else if(some)
donesomethingElse
return
throw SomeException
}
If the SomeException extends RuntimeException. Then you don't need to catch it even if the signature looks like that.
Also note that you can just remove the throws SomeException in that case. Read more here.
Yes, there are some unchecked exception, who might not be caught / rethrown.
Look at this tutorial - Unchecked Exceptions.
Even if SomeException is a checked exception, this can happen due to separate compilation.
Suppose you write a class:
public class B {
public static void foo() {
}
}
Then a class that calls it:
public class A {
public static void main(String[] args) {
B.foo();
}
}
Then say:
javac A.java
java A
All is fine. Now change B:
public class B {
public static void foo() throws java.io.IOException {
throw new java.io.IOException();
}
}
And this time just compile B before running:
javac B.java
java A
You get:
Exception in thread "main" java.io.IOException
at B.foo(B.java:4)
at A.main(A.java:4)
In the real world this happens when individual .jar files are updated after they've been modified by maintainers who don't understand the problems caused by adding more throws clauses.

Categories

Resources