How java matches Exception? - java

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 ..."

Related

Catch NumberFormatException has different behaviour?

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.

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

Exception Handling in Java to have Java best practices

I have a Java method like below:
private boolean getBooleanProperty(String property, String defaultValue) {
boolean result = false;
try {
result = Boolean.parseBoolean(properties.getProperty(property, defaultValue));
} catch (IllegalArgumentException | NullPointerException e) {
}
return result;
}
I know that the way I am handling the exceptions in above method is not correct and looking for the way to have those more aligned with the Java standards and best practices.
Similarly for the method below:
public void getStatusAndAnnotation(ITestResult result) {
try {
HashMap<Object, Object> map = new HashMap<>();
Method method = result.getMethod().getConstructorOrMethod().getMethod();
TestInfo annotation = method.getAnnotation(TestInfo.class);
try {
//add id removing the first character of the annotation (e.g. for C12034, send 12034)
if(annotation!=null) {
map.put("id",annotation.id().substring(1));
}
}catch (NullPointerException e){
e.printStackTrace();
}
if (result.getStatus() == ITestResult.SUCCESS) {
map.put("result", 1);
} else if (result.getStatus() == ITestResult.FAILURE) {
map.put("result", 9);
} else if (result.getStatus() == ITestResult.SKIP) {
map.put("result", 10);
}
if (annotation != null) {
if(annotation.trDeploy() && !map.get("id").equals(null) && !map.get("id").toString().isEmpty())
{
ApiIntegration.addTestResult(map);
}
else System.out.println("Deploying result was canceled, because test has annotation \"trDeploy: false\" or \"id\" has no value");
}
} catch (SecurityException | IOException
| ApiException | NullPointerException e) {
e.printStackTrace();
}
}
How do I handle these different exceptions to align with the best practices?
What I typically do is let the compiler/IDE tell me what exceptions I need to catch unless you want to catch an exception for a specific reason. That way, I can code without catching unnecessary exceptions and my code is cleaner.
These type of Exceptions are called Checked Exceptions
"In the Java class hierarchy, an exception is a checked exception if
it inherits from java.lang.Exception, but not from
java.lang.RuntimeException. All the application or business logic
exceptions should be checked exceptions."
Example:
try
{
// open a file (Compiler will force to either catch or throw)
}
catch (IOException ioe)
{
ioe.printStackTrace();
// need to make a decision on what to do here
// log it, wrap it in a RuntimeException, etc.
}
As for Unchecked Exceptions
"Unchecked, uncaught or runtime exceptions are exceptions that can be
thrown without being caught or declared"
Example:
String x = null;
// this will throw a NullPointerException
// However, you don't need to catch it as stated in some the comments
x.toString();
What you should do is prevent it
if (x == null)
{
x = "some default value"; // prevent the exception from happening.
}
x.toString();
Does this mean you should never catch a RuntimeException
No, of course not. It depends on the scenario.
Take this example:
String number = "12345";
// You don't know if number is a valid integer until you parse it
// If the string is not a valid number, then this code will
// throw an Exception
int i = Integer.parseInt(number);
Instead you can catch a NumberFormatException. Again, this is a form of prevention.
int i = 0; // some default
try
{
i = Integer.parseInt(number);
}
catch (NumberFormatException nfe)
{
// Good practice to log this, but the default int is fine.
}
Some Best Practices
Do not catch exceptions unless the compiler forces you to.
If you are catching a checked exception, then log it. You can also wrap it in a RuntimeException if you want it to percolate up the call stack.
If you want to catch a RuntimeException, then do so with a purpose (i.e. you can set a default and prevent the error all together.)
Don't have a chain of methods all throwing a checked Exception up the stack trace. This is very messing and forces all calling methods to either catch or throw the checked exception.
Catching a RuntimeException just to log it really doesn't have much of a purpose. Unless you are logging it in a catch all location.
Catch-All Example:
try
{
// entry point to application
}
catch (Throwable t)
{
// let all exceptions come here to log them
}

Java File Exception Handling

I am supposed to create a sample program for exception handling for file operations for my java assignment. I am having trouble understanding since I am a C++ guy. It would be really very helpful if somebody could point out the flaw in my code below. I am referring this article. Eclipse is giving me "Unreachable catch block for FileNotFoundException. This exception is never thrown from the try statement body" error.
import java.io.*;
public class file {
public static void main(String[] args) {
String arg1 = args[0];
String arg2 = args[1];
System.out.println(arg1);
System.out.println(arg2);
File f1, f2;
try {
f2 = new File(arg2);
f1 = new File(arg1);
}
catch(FileNotFoundException e) {
/*
if(!f1.exists()) {
System.out.println(arg1 + " does not exist!");
System.exit(0);
}
if(!f2.exists()) {
System.out.println(arg2 + " does not exist!");
System.exit(0);
}
if(f1.isDirectory()) {
System.out.println(arg1 + " is a Directory!");
System.exit(0);
}
if(f2.isDirectory()) {
System.out.println(arg2 + " is a Directory!");
System.exit(0);
}
if(!f1.canRead()) {
System.out.println(arg1 + " is not readable!");
System.exit(0);
}
if(!f2.canRead()) {
System.out.println(arg2 + " is not readable!");
System.exit(0);
}*/
}
}
}
Look at the docs for the File constructor you're calling. The only exception it's declared to throw is NullPointerException. Therefore it can't throw FileNotFoundException, which is why you're getting the error. You can't try to catch a checked exception which the compiler can prove is never thrown within the corresponding try block.
Creating a File object doesn't check for its existence. If you were opening the file (e.g. with new FileInputStream(...) then that could throw FileNotFoundException... but not just creating a File object.
This is because the constructor of class File with one argument
public File(String pathname)
Parameters:pathname - A pathname string Throws: NullPointerException - If the pathname argument is null
Throws: NullPointerException - If the pathname argument is null
throws only one exception and that is NullPointerException. Your code tries to catch a FileNotFoundException which is not related to NullPointerException and this is why you get this error in Eclipse.
One way to go is to catch exceptions of class Exception which is the super class of all exceptions in Java. Another way is to catch all the exceptions (each in different catch block) that the invoked construct throws (which can be easily obtained by going through its API). The third approach is to catch only the exceptions (again which are actually thrown by the construct) that make sense to your application and ignore the others.

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