Java has two ways of handling checked exceptions. This is very handy, and you need to know how to do both of them.
In your programs, you are expected to use TRY-CATCH instead of just "THROWS IOEXCEPTION", and also to use the TRY-WITH_RESOURCES syntax.
This is used to pass the exception to a higher up method which may be able to figure out what to do better.
Example - specifically for showing how to pass an exception to the calling method.
* main
calls getFile
* getFile
calls parseFN
static void main(String[] args) { boolean fileOpened = false; while (!fileOpened) { try { File f = getfile(); fileOpened = true; } catch (ParseExcption e) { System.out.println("You typed in a bad filename, try again"); //it will loop back ... } catch (IOException e) { System.out.println ("An IO exception occurred. Kill program!".) e.printStackTrace(); System.exit(0); } } } static File getFile() throws ParseException, IOException{ String fname = getFname(); fname = parseFN(fname); return new File(fname); } static String parseFN(String fname) throws ParseException{ // .... // if the file name is invalid, we'll throw an exception throw new ParseException("filename has invalid charachers",1); return fname; } |
In this example, we feel that the main program is the place where we want to decide what to do if there is an error.
This method, gets a filename, checks to see if it's valid by calling parseFN(), and then
This method, parseFN, checks to see if the filename is valid. If it is not, we don't know what exactly to do, so we'll throw
an exception. I'm using ParseException since it already exists and can be used for something like this. |
This structure is used to handle an exception. The exception can be one created in this method, or from a method lower down in the stack.
• TRY{} is used to surround the code that may cause an error.
• CATCH{} is used to surround the code that should be executed if there is an error
• CATCH must specify the exception that it wants to catch.
DO NOT WRITE catch (Exception e) {}
.
It is very bad style to just catch every exception.
try{
z = x / y;
}
catch(ArithmeticException e){
System.out.println("division by zero");
z = 0;
}
//program continues (instead of crashing)
Arithmetic Exceptions are unchecked exceptions so you do not have to put them in a try-catch block.
The fact that they do not need to be caught is a good indication that it is normally a bad idea to do this.
Do not write code to catch ArithmeticException or ArrayIndexOutOfBoundException or NullPointerException etc.
Here is the better way of coding it (without using exceptions).
if (y != 0) z = x / y; else z = 0;
The optional finally {}
block is always executed regardless of whether there is an error or not.
It is often used to close files, however, this is better done with "try with resources" (see below)
• The finally block will NOT be executed if program exits by calling System.exit().
• For each try block there can be zero or more catch blocks, but only one finally block.
You can catch multiple exceptions, however, only one exception at a time will be thrown and caught.
• All catch blocks must be ordered from most specific to most general i.e. catch for ArithmeticException must come before catch for Exception.
try{ ... } catch(ArithmeticException e){...} catch(ArrayIndexOutOfBoundsException e){...} catch(Exception e) {...} ← Do not actually do this In reality, don't catch any of these. The first two are unchecked exceptions.
try { ... } catch (MalformedURLException | IOException ex) { System.out.println(ex.toString()); }
From https://www.baeldung.com/java-try-with-resources
Support for try-with-resources — introduced in Java 7 — allows us to declare resources to be used in a try block with the assurance that the resources will be closed after the execution of that block. (The resources declared need to implement the AutoCloseable interface.) Simply put, to be auto-closed, a resource has to be both declared and initialized inside the try:
try (InputStream inFile = new FileInputStream("test")) { inFile.read(); ... //call a method here to do whatever you want with the data } catch(SomeException e) { ... } finally { //You probably won't need this. //No need to add code to close InputStream. Its close method will be internally called. //but if you do need something else, then you can put it here. }
In its simplest form:
try (PrintWriter writer = new PrintWriter(new File("test.txt"))) { writer.println("Hello World"); }We can declare multiple resources just fine in a try-with-resources block by separating them with a semicolon:
try (Scanner scanner = new Scanner(new File("testRead.txt")) ; PrintWriter writer = new PrintWriter(new File("testWrite.txt"))) { while (scanner.hasNext()) { writer.print(scanner.nextLine()); } }A try-with-resources block can still have the catch and finally blocks, which will work in the same way as with a traditional try block. You'll still need a catch block to do something with exceptions that are thrown.
Please continue on reading about File I/O now
For more information about try-catch, read JavaTPoint. This excellent site also explains "try with resources" very well.
Other sites:
javapapers
mykong
journaldev