I was trying to understand why to use exceptions.
Suppose if I have an program,
(without using try/catch)
public class ExceptionExample {
private static String str;
public static void main(String[] args) {
System.out.println(str.length());
}
I got exception
Exception in thread "main" java.lang.NullPointerException
at com.Hello.ExceptionExample.ExceptionExample.main(ExceptionExample.java:22)
Now using try/catch,
public class ExceptionExample {
private static String str;
public static void main(String[] args) {
try {
System.out.println(str.length());
} catch(NullPointerException npe) {
npe.printStackTrace();
}
}
}
I got Exception,
java.lang.NullPointerException
at com.Hello.ExceptionExample.ExceptionExample.main(ExceptionExample.java:9)
Now my question is,
In both the cases I have got the same message printed. So what is the use of using try/catch? and
What can we do after catching exception, in this case I have printed the stack trace. Is catch used only for printing the trace or for finding exception details using getMessage() or getClass()?
The difference is pretty big, actually.
Take the first one and add a line after the print:
public class ExceptionExample {
private static String str;
public static void main(String[] args) {
System.out.println(str.length());
System.out.println("Does this execute?");
}
}
You'll see that Does this execute? isn't printed because the exception interrupts the flow of the code and stops it when it isn't caught.
On the other hand:
public class ExceptionExample {
private static String str;
public static void main(String[] args) {
try {
System.out.println(str.length());
} catch(NullPointerException npe) {
npe.printStackTrace();
}
System.out.println("Does this execute?");
}
}
Will print both the stack trace and Does this execute?. That's because catching the exception is like saying, "We'll handle this here and continue executing."
One other remark, the catch block is where error recovery should happen, so if an error occurs but we can recover from it, we put the recovery code there.
Edit:
Here's an example of some error recovery. Let's say we have a non-existent file at C:\nonexistentfile.txt. We want to try and open it, and if we can't find it, show the user a message saying it's missing. This could be done by catching the FileNotFoundException produced here:
// Here, we declare "throws IOException" to say someone else needs to handle it
// In this particular case, IOException will only be thrown if an error occurs while reading the file
public static void printFileToConsole() throws IOException {
File nonExistent = new File("C:/nonexistentfile.txt");
Scanner scanner = null;
try {
Scanner scanner = new Scanner(nonExistent);
while (scanner.hasNextLine()) {
System.out.println(scanner.nextLine());
}
} catch (FileNotFoundException ex) {
// The file wasn't found, show the user a message
// Note use of "err" instead of "out", this is the error output
System.err.println("File not found: " + nonExistent);
// Here, we could recover by creating the file, for example
} finally {
if (scanner != null) {
scanner.close();
}
}
}
So there's a few things to note here:
We catch the FileNotFoundException and use a custom error message instead of printing the stack trace. Our error message is cleaner and more user-friendly than printing a stack trace. In GUI applications, the console may not even be visible to the user, so this may be code to show an error dialog to the user instead. Just because the file didn't exist doesn't mean we have to stop executing our code.
We declare throws IOException in the method signature instead of catching it alongside the FileNotFoundException. In this particular case, the IOException will be thrown here if we fail to read the file even though it exists. For this method, we're saying that handling errors we encounter while reading the file isn't our responsibility. This is an example of how you can declare an irrecoverable error (by irrecoverable, I mean irrecoverable here, it may be recoverable somewhere further up, such as in the method that called printFileToConsole).
I accidentally introduced the finally block here, so I'll explain what it does. It guarantees that if the Scanner was opened and an error occurs while we're reading the file, the Scanner will be closed. This is important for many reasons, most notably that if you don't close it, Java will still have the lock on the file, and so you can't open the file again without exiting the application.
There are two cases when you should throw an exception:
When you detect an error caused by incorrect use of your class (i.e. a programming error) throw an instance of unchecked exception, i.e. a subclass of RuntimeException
When you detect an error that is caused by something other than a programming error (invalid data, missing network connectivity, and so on) throw an instance of Exception that does not subclass RuntimeException
You should catch exceptions of the second kind, and not of the first kind. Moreover, you should catch exceptions if your program has a course of action to correct the exceptional situation; for example, if you detect a loss of connectivity, your program could offer the user to re-connect to the network and retry the operation. In situations when your code cannot adequately deal with the exception, let it propagate to a layer that could deal with it.
try/catch will prevent your application from crashing or to be precise- the execution will not stop if an unintentional condition is met. You can wrap your "risky" code in try block and in catch block you can handle that exception. By handling, it means that do something about that condition and move on with execution.
Without try/catch the execution stopped at the error-making-line and any code after that will not be executed.
In your case, you could have printed "This was not what I expected, whatever, lets move on!"
Let's say you are connected to database but while reading the records, it throws some exception. Now in this particular case, you can close the connection in Finally block. You just avoided memory leak here.
What I meant to say is , you can perform your task even if exception is thrown by catching and handling it.
In the example you've given, you're right, there is no benefit.
You should only catch an exception if either
You can do something about it (report, add information, fix the situation), or
You have to, because a checked exception forces you to
Usual "handling" of an exception is logging the situation to a log file of your choosing, adding any relevant context-sesitive information, and letting the flow go on. Adding contextual information benefits greatly in resolving the issue. So, in your example, you could have done
public static void main(String[] args) {
try {
System.out.println(str.length());
} catch(NullPointerException npe) {
System.err.println(
"Tried looking up str.length from internal str variable,"
+" but we got an exception with message: "
+ npe.getMessage());
npe.printStackTrace(System.err);
}
}
when looking a message like that, someone will know based on the message what went wrong and maybe even what might be done to fix it.
If you are using Exception, don't
catch(NullPointerException npe) {
npe.printStackTrace();
}
simply
catch(NullPointerException npe) {
//error handling code
}
You are menat to remove error printing. And anyways catch general exception not just specific ones.
If you look at the two exceptions, they are actually different. The first one is referring to line 22, while the second one is referring to line 9. It sounds like adding the try/catch caught the first exception, but another line of code also threw an exception.
Consequently, the exception is being thrown because you never created a new String, or set a value to the string, unless it was done in a part of the code that is not shown.
Adding a try/catch block can be very helpful with objects that you have little to no control over, so if these objects are other than expected (such as null), you can handle the issue properly.
A string is normally something that you would instantiate first, so you shouldn't normally have to worry about using a try/catch.
Hope this helps.
To answer your original question Che, "when to use an exception?"
In Java - I'm sure you've already found out... There are certain methods in Java that REQUIRE the try / catch. These methods "throw" exceptions, and are meant to. There is no way around it.
For example,
FileUtils.readFileToString(new File("myfile.txt"));
won't let you compile until you add the try/catch.
On the other hand, exceptions are very useful because of what you can get from them.
Take Java Reflection for example...
try { Class.forName("MyClass").getConstructor().newInstance(); }
catch ( ClassNotFoundException x ) { // oh it doesnt exist.. do something else with it.
So to answer your question fully -
Use Try/Catch sparingly, as it's typically "frowned on" to EXPECT errors in your application.. on the contrary, use them when your methods require them.
Related
void appendFile() throws IOException{
FileWriter print = new FileWriter(f, true);
String info = GetData.getWord("Write desired info to File");
print.append(" "); //Write Data
print.append(info);
System.out.println("this executes");
print.flush();
print.close();
}
boolean fileExist(){
return f.exists();
}
try{
if (f.fileExist())
f.appendFile();
else {
throw new IOException();
}
}
catch(IOException e) {
e.printStackTrace();
}
I'm not sure if the ecxeption is well handeled? The FileWriter is not going to be created if there is a fileNotFoundException, therefore don't need to be closed. However, is it possible that this code throws another kind of IOException after the file was opened?, and in that case do I need a finally block to close the file.
No.
It doesn't safely close the resource
The general rule is, if you call a constructor of an object that represents a closable resource, or a method that returns one which documents that this counts as 'opening the resource', which often but not always includes new being part of the method name (examples: socket.getInputStream(), Files.newInputStream), then you are responsible for closing it.
The problem is, what if an exception occurs? So, you have to use try/finally, except that's a mouthful, so there's a convenient syntax for this.
The appendFile method should use it; it isn't, that makes it bad code. This is correct:
try (FileWriter print = new FileWriter(f, true)) {
String info = GetData.getWord("Write desired info to File");
print.append(" "); //Write Data
print.append(info);
System.out.println("this executes");
}
Not how it is not neccessary to flush before close (close implies flush), and in this case, not neccessary to close() - the try construct does it for you. It also does it for you if you get out of the {} of the try via a return statement, via control flow (break), or via an exception, or just by running to the } and exiting normally. No matter how - the resource is closed. As it should be.
It throws description-less exceptions
else throw new IOException(); is no good; add a description that explains why the exception happened. throw new IOException("File not found") is better, but throw new FileNotFoundException(f.toString()) is even better: The message should convey useful information and nothing more than that (in other words, throw new IOException("Something went wrong") is horrible, don't do that, that message adds no useful information), should not end in punctuation (throw new IOException("File not found!") is bad), and should throw a type that is most appropriate (if the file isn't there, FileNotFoundException, which is a subtype of IOException, is more appropriate, obviously).
It commits the capital offense
You should not ever write a catch block whose contents are just e.printStackTrace();. This is always wrong.
Here's what you do with a checked exception:
First, think of what the exception means and whether the nature of your method inherently implies that this exception can occur (vs. that it is an implementation detail). In this case, you didn't show us what the method containing that try/catch stuff even does. But let's say it is called appendFile, obviously a method that includes the text 'file' does I/O, and therefore, that method should be declared with throws IOException. It's not an implementation detail that a method named appendFile interacts with files. It is its nature.
This is somewhat in the eye of the beholder. Imagine a method named saveGame. That's less clear; perhaps the mechanism to save may involve a database instead, in which case SQLException would be normal. That's an example of a method where 'it interacts with the file system' is an implementation detail.
The problem that the exception signals is logical, but needs to be more abstract.
See the above: A save file system can obviously fail to save, but the exact nature of the error is abstract: If the save file system is DB-based, errors would show up in the form of an SQLException; if a file system, IOException, etcetera. However, the idea that saving may fail, and that the code that tried to save has a reasonable chance that it can somewhat recover from this, is obvious. If it's a game, there's a user interface; you should most absolutely TELL the player that saving failed, instead of shunting some stack trace into sysout which they probably never even look at! Telling the user that something failed is one way of handling things, not always the best, but here it applies).
In such cases, make your own exception type and throw that, using the wrapper constructor:
public class SaveException extends Exception {
public SaveException(Throwable cause) {
super(cause);
}
}
// and to use:
public void save() throws SaveException {
try {
try (OutputStream out = Files.newOutputStream(savePath)) {
game.saveTo(out);
}
} catch (IOException e) {
throw new SaveException(e);
}
}
If neither applies, then perhaps the exception is either essentially not handleable or not expectable or nearly always a bug. For example, writing to an outputstream that you know is a ByteArrayOutputStream (which can't throw), trying to load the UTF-8 charset (which is guaranteed by the JVM spec and therefore cannot possibly throw NoSuchCharsetException) - those are not expectable. Something like Pattern.compile("Some-regexp-here") can fail (not all strings are valid regexps), but as the vast majority of regexes in java are literals written by a programmer, any error in them is therefore neccessarily a bug. Those, too, are properly done as RuntimeExceptions (which are exceptions you don't have to catch or list in your throws line). Not handleables are mostly an application logic level thing. All fair game for runtimeexceptions. Make your own or use something that applies:
public void save(int saveSlot) {
if (saveSlot < 1 || saveSlot > 9) throw new IllegalArgumentException("Choose a saveslot from 1 to 9");
// ... rest of code.
}
This really feels like door number one: Whatever method this is in probably needs to be declared as throws IOException and do no catching or trying at all.
Minor nit: Uses old API
There's new API for file stuff in the java.nio.file package. It's 'better', in that the old API does a bunch of bad things, such as returning failure by way of a boolean flag instead of doing it right (by throwing an exception), and the new API has far more support for various bits and bobs of what file systems do, such as support for file links and creation timestamps.
In Java, is there an elegant way to detect if an exception occurred prior to running the finally block? When dealing with "close()" statements, it's common to need exception handling within the finally block. Ideally, we'd want to maintain both exceptions and propagate them up (as both of them may contain useful information). The only way I can think of to do this is to have a variable outside the try-catch-finally scope to save a reference to a thrown exception. Then propagate the "saved" exception up with any that occur in the finally block.
Is there a more elegant way of doing this? Perhaps an API call that will reveal this?
Here's some rough code of what I'm talking about:
Throwable t = null;
try {
stream.write(buffer);
} catch(IOException e) {
t = e; //Need to save this exception for finally
throw e;
} finally {
try {
stream.close(); //may throw exception
} catch(IOException e) {
//Is there something better than saving the exception from the exception block?
if(t!=null) {
//propagate the read exception as the "cause"--not great, but you see what I mean.
throw new IOException("Could not close in finally block: " + e.getMessage(),t);
} else {
throw e; //just pass it up
}
}//end close
}
Obviously, there are a number of other similar kludges that might involve saving the exception as an member variable, returning it from a method, etc... but I'm looking for something a bit more elegant.
Maybe something like Thread.getPendingException() or something similar? For that matter, is there an elegant solution in other languages?
This question actually spawned from comments in another question that raised an interesting question.
Your idea about setting a variable outside the scope of the try/catch/finally is correct.
There cannot be more than one exception propagating at once.
Instead of using a Boolean flag, I would store a reference to the Exception object.
That way, you not only have a way to check whether an exception occurred (the object will be null if no exception occurred), but you'll also have access to the exception object itself in your finally block if an exception did occur. You just have to remember to set the error object in all your catch blocks (iff rethrowing the error).
I think this is a missing C# language feature that should be added. The finally block should support a reference to the base Exception class similar to how the catch block supports it, so that a reference to the propagating exception is available to the finally block. This would be an easy task for the compiler, saving us the work of manually creating a local Exception variable and remembering to manually set its value before re-throwing an error, as well as preventing us from making the mistake of setting the Exception variable when not re-throwing an error (remember, it's only the uncaught exceptions we want to make visible to the finally block).
finally (Exception main_exception)
{
try
{
//cleanup that may throw an error (absolutely unpredictably)
}
catch (Exception err)
{
//Instead of throwing another error,
//just add data to main exception mentioning that an error occurred in the finally block!
main_exception.Data.Add( "finally_error", err );
//main exception propagates from finally block normally, with additional data
}
}
As demonstrated above... the reason that I'd like the exception available in the finally block, is that if my finally block did catch an exception of its own, then instead of overwriting the main exception by throwing a new error (bad) or just ignoring the error (also bad), it could add the error as additional data to the original error.
You could always set a boolean flag in your catch(es). I don't know of any "slick" way to do it, but then I'm more of a .Net guy.
Use logging...
try {
stream.write(buffer);
} catch(IOException ex) {
if (LOG.isErrorEnabled()) { // You can use log level whatever you want
LOG.error("Something wrong: " + ex.getMessage(), ex);
}
throw ex;
} finally {
if (stream != null) {
try {
stream.close();
} catch (IOException ex) {
if (LOG.isWarnEnabled()) {
LOG.warn("Could not close in finally block", ex);
}
}
}
}
In vb.net, it's possible to use a "Catch...When" statement to grab an exception to a local variable without having to actually catch it. This has a number of advantages. Among them:
If nothing is going to 'ultimately' catch the exception, an unhandled exception trap will be fired from the spot of the original exception. Much nicer than having the debugger trap at the last rethrow, especially since information that might be needed for debugging won't yet have gone out of scope or been swept up by 'finally' statements.
Although a rethrow won't clear the stack trace the way "Throw Ex" would, it will still often jinx the stack trace. If the exception isn't caught, the stack trace will be clean.
Because this feature is unsupported in vb, it may be helpful to write a vb wrapper to implement the code in C (e.g. given a MethodInvoker and an Action(Of Exception), perform the MethodInvoker within a "Try" and the Action in a "Finally".
One interesting quirk: it's possible for the Catch-When to see an exception which will end up getting overwritten by a Finally-clause exception. In some cases, this may be a good thing; in other cases it may be confusing. In any event, it's something to be aware of.
I'm trying to open and read a file passed from the command line.
This is what I have so far:
import java.io.*;
public class Test {
public static void main(String[] args) throws FileNotFoundException {
if ( (args[0].length() == 0) || (args[0] == null) || (args[0].isEmpty()) ) {
System.err.println("Usage Error: No file name was provided.");
System.exit(1);
}
File file = new File(args[0]);
if (!file.exists()) {
System.err.println("Usage Error: The file, " + args[0] + ", does not exist.");
}
if (!file.canRead()) {
System.err.println("Usage Error: The file, " + args[0] + ", cannot be read.");
}
} // main
}
I am not entirely sure how I should be handling file not found exceptions. My teacher has mentioned try/catch blocks but I wasn't sure if I needed those here. Is it sufficient to just test to see if the file was passed as an argument and if it wasn't use the System.err.print() method to give the user an error?
Also, if System.err.print() is called does it exit the program after that (meaning, do I need to include System.exit(1) after that)? Or is it better (in terms of design) to just do something like this:
public void readFile() throws FileNotFoundException {
// try to open file here
}
public static void main(String[] args) {
try {
readFile();
} catch (Exception e) {
// exception handled here
}
}
I just need to make sure the user actually passes a string as the file name and that it exists/can be read.
Exceptions make it easier to deal with errors programmatically.
Meaning: when your program only consists of a main function, and you want to tell the user about "a file is not there"; then it doesn't make too much of a difference, if your program prints a reasonable message to stderr; and then exists with some non-zero return code; or if you throw an exception.
To the contrary; in your simple example; having one precise error message is actually to be preferred over throwing an exception and having the JVM print a (potentially confusing) stack trace to the user.
But: your current program is just a small example thing. As soon as things grow bigger, your program consists of calls to many different classes in different components. And then printing to stderr isn't a good idea any more. Then you want to make sure that one layer that runs into a problem has a defined way to communicate this situation; and that is what exceptions are meant for. In such situations, you very much prefer exceptions; because some higher layer can catch them - to then decide what to do. For example the program could decide to show the error message on some UI panel; or to put a message into a log file; or to send a text message to some mobile phone. All of that would be close to impossible, if you only printed to stderr.
In catch instead // exception handled here you can write any code you want.
If you just throwing exception - java itself doing some standart things.
Take your time and read Effective Java (2nd Edition) book form Joshua Bloch.
Item 57 (Use exceptions only for exceptional conditions) in chapter Exceptions will clarify everything in this topic.
I am a Java beginner and knows that try...catch statements are used to handle exceptions; means when an exception is thrown by try block, catch block is executed. So,my question is when I tried the following code (without try catch) it throws a unreported IOException in read() method but when I use try catch it works fine.
Why doesn't the control get transferred to catch statement when the above mentioned exception occurs in the try block and exception occured is printed?
here is my code:
class Test00 {
public static void main(String args[]) {
char ch;
try {
ch=(char)System.in.read();//here exception is thrown without using try..catch
System.out.println(ch);
} catch(Exception e) {
System.out.print("exception occured");
}
}
}
I think the compiler is saying to throw an exception,that's why the code worked with try catch.But why not the catch block is executed?is i am getting something wrong.
The compiler is telling you that the exception could be thrown, and that you have to cater for that possibility.
The compiler is doing a static analysis of your code. It can't tell how the code will actually run in practise.
This can be frustrating. e.g. if I write:
new URL("http://www.stackoverflow.com");
the compiler will insist that I catch a MalformedURLException. It's clear that URL is fine, but the compiler warns me since I could construct a URL object using:
new URL(potentiallyDubiousUserInput);
and I can't guarantee what that string potentiallyDubiousUserInput is going to be.
These are known as checked exceptions and you have to handle them (either catch or declare them to be thrown further). They can be a pain, and you'll see in languages such as Scala that all exceptions are unchecked. That is, you don't explicitly have to handle them.
See this question/answer for more info.
You have to distinguish (and tell us clearly, so that we don't have to puzzle it out) between what the compiler is telling you and what happens at runtime.
In your case, without the try-catch the compiler was telling you that the read() might throw, and that you would have to deal with the exception somehow. That's what you did by adding the try-catch.
However, when you then ran the program, it didn't actually throw (and generally speaking, it's very unlikely that this program will throw), so it never entered the catch block.
This is because System.in.read() can throw IOException which is a checked Exception. And as mentioned in JLS 11.2.3 about checked exception:
It is a compile-time error if a method or constructor body can throw some exception class E when E is a checked exception class and E is not a subclass of some class declared in the throws clause of the method or constructor.
The goal is to be able to do:
throw new RuntimeException();
without it printing:
Exception in thread "main" java.util.RuntimeException
at grame.GrameManager.add(GrameManager.java:40)
at grame.GrameManager.add(GrameManager.java:47)
at grame.Entity.<init>(Entity.java:56)
at grame.Entity.<init>(Entity.java:28)
at test.Test.main(Test.java:20)
(for example).
Is this possible? If so, how would I go about doing this?
Since exceptions are important, you could use a logging mechanism like log4j (http://logging.apache.org/log4j/1.2/) and set the logging to a different level when you don't want some exceptions to be printed or log to a file instead of console for example.
If you just don't care about the exception, catch it and do nothing with it (empty catch, which is awful).
You can redirect System.err by setting System.setErr(null);
No thrown exception ever directly generates a stacktrace to the error console. It's up to the code who is calling it to do so. In the case of a main program:
public static void main(String args[]) throws Exception {
// do something that throws an exception
}
If you don't catch the exception, the system will actually spit it out to the console i believe.
Somewhere along the way, you need to deal with the exception. If showing it in the GUI is what you want, then you'll have to do something like this:
public interface ExceptionHandler {
void handleException(Exception e);
}
public static void main(String args[]) {
ExceptionHandler exceptionHandler = ...;
try {
// something that might throw an exception
}
catch (Exception e) {
exceptionHandler.handle(e);
}
}
Just catch the exception, and don't put anything in the catch block.
I should add that doing this is generally a bad idea. Having that stack trace, or some sort of message is very useful when finding out what went wrong in your program.
If you want the method to kill the program without printing a stack trace, place it in a try/catch block, and under catch simply use the statement:
System.exit(1)
This lets the system know that the program exited with an irregular (non-zero) state, but does not print anything to System.err.
All that you really need to do is catch it... However, this is a really bad idea. You may want to make your own exception and catch that. This way you will not swallow exceptions that you should not be ignoring. The only time that you should really consider to do this, is if you cannot allow your application to blow up. If that is the case then you should at the very least log the error.
This explains it better than I can (and is a good resource regardless). Basically, it suggests that:
"If a client can reasonably be expected to recover from an exception,
make it a
checked exception. If a client cannot do anything to recover from the exception,
make it an unchecked exception".
Like this:
try {
some code...
} catch (RuntimeException e) {
}
1. Java compiler only cares during compilation that you have given a catch for a try, whether you implement any code in the catch or not.
2. You can keep the catch block empty, or print it on the console, log it..etc....
eg:
try{
}catch(Exception ex){
}
3. But printStackTrace() prints the method name, class name , file name and the line number where the exception has occurred.