Catch NumberFormatException has different behaviour? - java

I was writing a code to show examples of try/catch and I notice that the same catch NumberFormatException was triggered or not depending on where I use it. This is the code:
public class Main {
public static void main(String[] args) {
System.out.println("3/0 => Result: " + divide(3,0)); // returns 3/0 => Result: null
System.out.println("6/2 => Result: " + divide(6,2)); // returns 3/0 => Result: 3
// System.out.println("6/home => Result: " + divide(Integer.parseInt("home"),1));
try {
System.out.println("6/home => Result: " + divide(Integer.parseInt("home"),1));
} catch (NumberFormatException e) {
System.out.println("Error type: NumberFormatException (MAIN METHOD)");
}
}
static Integer divide(int n1, int n2) { // we used Integer (wrapper class) to be able to return null
int result = 0;
try {
result = n1 / n2;
} catch (ArithmeticException e) {
System.out.println("Error type: ArithmeticException");
return null;
} catch (NumberFormatException e) {
System.out.println("Error type: NumberFormatException");
return null;
}
return result;
}
}
The code returns:
Error type: ArithmeticException
3/0 => Result: null
6/2 => Result: 3
Error type: NumberFormatException (MAIN METHOD)
But if I enable the 3rd line:
System.out.println("6/home => Result: " + divide(Integer.parseInt("home"),1));
And disable the try/catch inside main method the NumberFormatException inside the divide method does not trigger and it crash the program.
Can anyone explain why? I am using the same exception type, why it works inside the main method but it does not work inside the divide method?

It's because the Integer.parseInt method is called from the main method and not inside try / catch block. Look at the stack trace that should be printed out.
Exception in thread "main" java.lang.NumberFormatException: For input string: "home"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:580)
at java.lang.Integer.parseInt(Integer.java:615)
at Main.main(Main.java:6)
The last line (Main.main(Main.java:6)) is giving you a clear hint from where the exception was thrown out in your code.

Catching exceptions is depending on the exception happening inside the corresponsing try{} block. By disabling the try / catch inside the main method the occuring number format exception is not in any try{} block anymore and therefore "crashes" your program. The try / catch inside the divide method is in that case never even reached, as the exception happens while the thread is executing the code 'Integer.parseInt("home")' which is outisde of that block / inside your main method.

Related

How java matches Exception?

public class ExceptionDemo {
public static void main(String[] args) {
try {
int x = Integer.parseInt(args[0]);
System.out.printf("try: x = %d\n", x);
int z = 42 / x;
System.out.printf("try: z = %d\n", z);
return;
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("ArrayIndexOutOfBoundsException: " + e.getMessage());
} catch (NumberFormatException e) {
System.out.println("NumberFormatException: " + e.getMessage());
} catch (ArithmeticException e) {
System.out.println("ArithmeticException: " + e.getMessage());
} catch (Exception e) {
System.out.println("Exception: " + e.getMessage());
} finally {
System.out.println("finally");
}
System.out.println("end");
}
}
When I try input 0,java catches "ArithmeticException".
The question is how java knows ArithmeticException is ArithmeticException?
So I look for ArithmeticException class.
public class ArithmeticException extends RuntimeException {
private static final long serialVersionUID = 2256477558314496007L;
/**
* Constructs an {#code ArithmeticException} with no detail
* message.
*/
public ArithmeticException() {
super();
}
/**
* Constructs an {#code ArithmeticException} with the specified
* detail message.
*
* #param s the detail message.
*/
public ArithmeticException(String s) {
super(s);
}
}
There is no special in ArithmeticException class.
How the java detect the error "42/0" is the ArithmeticException?
Just because ArithmeticException extends RuntimeException?
I guess your question is, how does Java know that it should throw an ArithmeticException when you try to divide by 0?
Because the language specification says so:
JLS Section 15.17.2
...On the other hand, if the value of the divisor in an integer division is 0, then an ArithmeticException is thrown.
That's it. Because it says so, it does so.
I can't explain this any further because we can't know the implementations of operators like / unless we look at the source code of the Java compiler. If it's a method, we can just read the source code of the JDK.
The way try/catch work is as following (taken from here)
The catch block contains code that is executed if and when the
exception handler is invoked. The runtime system invokes the exception
handler when the handler is the first one in the call stack whose
ExceptionType matches the type of the exception thrown. The system
considers it a match if the thrown object can legally be assigned to
the exception handler's argument.
So basically when an exception is thrown, the code will walk through all of your catch statement to see if any of the catch clause matches the exception ("match" = "can be assigned to the exception handler's argument"). If there's a match, the corresponding exception handler will be invoke. If there's none, the exception will be bubbled up to the caller.
Another way to look at this is if you have your code like this:
try {
// 42/ 0
} catch (Exception e) {
System.out.println("Got Exception");
} catch (ArithmeticException e) {
System.out.println("ArithmeticException: " + e.getMessage());
}
Then you'll see that it will always print "Got Exception" and not the "ArithmeticException ..."

java exception string filter

When throw exception, I found that always included java.lang.exception or javax.ssl.xxxx and so on, I just want to get only messages but not including exception type, how can I do it?
As exception has many types, I can not just filter string start with, is it available to do so?
Find below a small snippet as demonstration for my comment
try {
int i = 1 / 0;
} catch (Exception e) {
System.out.println("exception = " + e);
System.out.println("getMessage = " + e.getMessage());
}
output
exception = java.lang.ArithmeticException: / by zero
getMessage = / by zero

Java: try/catch with InputMismatchException creates infinite loop while reading of a file

I have a task to make a program that will add up all the valid integers in a file and to ignore anything that isn’t a valid int. I have to use Try and Catch.
File Numbers = new File("Numbers.txt");
Scanner readFile = null;
int i = 0;
int total= 0;
boolean success = false;
while(!success){
try {
readFile = new Scanner(Numbers);
while(readFile.hasNext()){
i = readFile.nextInt();
System.out.println(i);
total = i + total;
};
success = true;// Ends The loop
} catch (FileNotFoundException e1) {
System.err.println(Numbers.getName()+" does not exist");
}
catch(InputMismatchException e2){
System.err.println("Data incorrect type expecting an int found: " + readFile.nextLine());
readFile.next();
}
System.out.println("total is: " + total);
};
The problem is that the program gets caught in an infinite loop, where instead of going past the exception it just starts again.The task seems pretty straight forward, yet i don't know why it wont work?
You fall into infinite loop because when exception happens, the success variable didn't change its value to true. In order to do some action even when exception happens you should add the finnaly block. It could look like this:
try {
// do some stuff
} catch (Exception e) {
// catch the exception
} finally {
if (!readFile.hasNext()) success = true;
}
And by the way, never do this: catch (Exception e), I did it just for example sake. Instead always catch the specific exception. Because Exception is the most basic class in the exception hierarchy, so it will catch up all the exceptions, and unless you re-throw it you could have false feeling of "safiness". When you want to catch all the exceptions, you should do this:
try {
// do stuff
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
e.printStackTrace(); // or other approptiate action, i.e. log it.
}
Assume any of the following FileNotFound or InputMismatchException exceptions will raise, then your program wont change success to true. Thus it returns to the outer while loop and read the same file. Because nothing has changed the same Exception will be thrown again.
==> Endless loop.
To fix that I suggest to move the try/catch block to the inner while.

Try catch exception (letter in int)

I'm trying to use a try catch structure to show an error when I try to input a letter into a string. Which exception should I be using for this? the console shows me InputMismatchException but this does not work.
input that works:
beginnen = 1
input that doesn't work:
beginnen = a
it obviously doesn't work cause i'm putting a string into an int, I just want to have a message show up when this occurs
int beginnen;
String error = "Something went wrong";
try {
beginnen = Input.readInt();
}
catch (InputMismatchException IME) {
System.out.println(error);
}
error that shows up:
Exception in thread "main" java.util.InputMismatchException
If the documentation is foggy, use experiment:
try {
beginnen = Input.readInt();
} catch (Throwable x) {
System.err.println("Catched "+x.getClass().getName());
}
This will print the exact class name for you and you can later change your code to catch the exception of this class. This will also show for you, maybe just nothing is actually thrown.
Your Try/Catch expression looks fine to me, however you've mistakenly referenced error, which is not defined anywhere.
Try changing it to System.out.println(IME.getMessage());

Getting error number of an exception object

I have a program developed and it has a single entry point. A Try catch block is surrounding it.
try {
Runner runner = new Runner();
// Adhoc code
UIManager.setLookAndFeel(new NimbusLookAndFeel());
runner.setupVariables();
runner.setLookAndFeel();
runner.startSessionFactory();
runner.setupApplicationVariables();
runner.setupDirectories();
// This will be used to test out frames in development mode
if (Runner.isProduction == true) {
execute();
} else {
test();
}
} catch (Exception e) {
SwingHelper.showErrorMessageMainFrame(e.getMessage());
Logger.getRootLogger().error(e);
e.printStackTrace();
}
But suppose a null pointer exception is thrown, the message box is empty since the Exception doesn't contain a message. For this I added a logic-
if(e instanceof NullPointerException){
NullPointerException n =(NullPointerException) e;
SwingHelper.showErrorMessageMainFrame("Unexpected Exception due at ");
}else{
SwingHelper.showErrorMessageMainFrame(e.getMessage());
}
This works all fine but I also want the line number to be displayed. How can I get it done. How can I get the line number of the exception?
Among the answer to this question, you can use this snippet:
public static int getLineNumber() {
return Thread.currentThread().getStackTrace()[2].getLineNumber();
}
Althought is recommended to use a logging library such as log4j.
The metadata for the exception is stored in StackTraceElement class, which you can get from your exception by calling getStackTrace().
Example of using it is:
if (e instanceof NullPointerException) {
NullPointerException n = (NullPointerException) e;
StackTraceElement stackTrace = n.getStackTrace()[0];
SwingHelper.showErrorMessageMainFrame("Unexpected Exception due at " + stactTrace.getLineNumber());
}
if(e instanceof NullPointerException){
NullPointerException n =(NullPointerException) e;
SwingHelper.showErrorMessageMainFrame("Unexpected Exception due at line" + e.getStackTrace()[0].getLineNumber());
} else {
SwingHelper.showErrorMessageMainFrame(e.getMessage());
}
Wow I was ninja'd by those above...
EDIT: Forgot to indent

Categories

Resources