Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Software Development Continuous Education Java Programmer I Certification Part 7 5/24/2017 1 Session Overview • Exceptions Handling – – – – – Exceptions in Java What happens when an exception is thrown? Categories of exceptions Common exception classes and categories Practice exam questions 5/24/2017 2 Exceptions Handling • In Java, an exceptional condition can affect the normal code flow. In this chapter, we’ll look at how to handle Java exceptions depending on the nature of the exceptional condition, you may or may not be able to recover completely. In the exam, you’ll be tested on Java code with respect to exceptions. This chapter covers the following: – – – – – Understanding and identifying exceptions arising in code Determining how exceptions alter the normal program flow Understanding the need to handle exceptions separately in your code Using try-catch-finally blocks to handle exceptions Differentiating among checked exceptions, unchecked exceptions, and errors – Invoking methods that may throw exceptions – Recognizing common exception categories and classes • Our focus in this chapter will be on the exam objectives and what you need to know about exceptions. This chapter will not cover advanced exceptions topics such as try statement with multiple catch clauses, automatic closing of resources with a try-with-resources statement, or the creation of custom exceptions. These topics are covered in the next level of Java certification (in the OCP Java SE 7 Programmer II exam). 3 5/24/2017 Exceptions in Java • In this section, we’ll learn what exceptions are in Java, why you need to handle exceptions separately from the main code, and all about their advantages and disadvantages. • A taste of exceptions – Sample exceptions: public class ArrayAccess { public static void main(String args[]) { String[] students = {"Shreya", "Joseph", null};//array length is 3 System.out.println(students[5].length()); //array index out of bound } } public class OpenFile { public static void main(String args[]) { //class FileInputStream throws FileNotFoundException exception FileInputStream fis = new FileInputStream("file.txt"); } } public class MethodAccess { public static void main(String args[]) { myMethod(); } public static void myMethod() { System.out.println("myMethod"); //infinite loop causes StackOverflowError exception at runtime myMethod(); } 5/24/2017 } 4 Exceptions in Java • Why handle exceptions separately? – Example of exceptions handling: try { Access the blogging website //required code block Login to your account Select the blog to be commented on Post your comments } catch (WebsiteUnavailableException e) { //exception 1 handling code // define code to execute if website not available } catch (LoginUnsuccesfulException e) { //exception 2 handling code // code to execute if login is unsuccessful } catch (DatabaseAccessException e) { //exception 3 handling code // code to execute if data for particular // post cannot be accessed } Note: Because the exception handlers are defined separately, any confusion with main program code is clarified. Additionally, this code doesn’t compromise on checking the completion of a step before moving on to the next step because of separated appropriate exception handlers. 5/24/2017 5 Exceptions in Java • Do exceptions offer any other benefits? – Apart from separating concerns between defining the regular program logic and the exception handling code, exceptions also can help pinpoint the offending code (code that throws an exception), together with the method in which it is defined, by providing a stack trace of the exception or error. – Example: public class Trace { // line 1 public static void main(String args[]) { // line 2 method1(); // line 3 } // line 4 public static void method1() { // line 5 method2(); // line 6 } // line 7 public static void method2() { // line 8 String[] students = {"Shreya", "Joseph"}; // line 9 System.out.println(students[5]); // line 10 } // line 11 } // line 12 – method2() tries to access the array element of students at index 5, which is an invalid index for array students, so the code throws the exception ArrayIndexOutOfBounds - exception at runtime as shown below: Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5 at Trace.method2(Trace.java:10) at Trace.method1(Trace.java:6) 5/24/2017 at Trace.main(Trace.java:3) 6 What happens when exception is thrown? • In this section, we’ll uncover what happens when an exception is thrown in Java. We’ll work through examples to learn how the normal flow of code is disrupted when an exception is thrown. We’ll also define an alternative program flow for code that may throw exceptions. – As with all other Java objects, an exception is an object. All types of exceptions subclass java.lang.Throwable. When a piece of code hits an obstacle in the form of an exceptional condition, it creates an object of class java.lang.Throwable (at runtime an object of the most appropriate subtype is created), initializes it with the necessary information (such as its type, an optional textual description, and the offending program’s state), and hands it over to the JVM. The JVM raises this exception condition and looks for an appropriate code block that can “handle” this exception. – The JVM keeps an account of all the methods that were called when it hit the offending code, so to find an appropriate exception handler it looks through all of the tracked method calls. – To understand how an exception propagates through method calls, it’s important to understand how method calls work. An application starts its execution with the method main, and main may call other methods. When main calls another method, the called method should complete its execution before main can complete its own execution. – An operating system (OS) keeps track of the code that it needs to execute using a stack. A stack is a type of list in which the items that are added last to it are the first ones to be taken off it—Last In First Out. This stack uses a stack pointer to point to 5/24/2017 the instructions that the OS should execute. 7 What happens when exception is thrown? • From previous example, here’s a step-by-step discussion of exception propagation: – When the method main starts its execution, its instructions are pushed onto the stack. – The method main calls the method method1, and instructions for method1 are pushed onto the stack. (at Trace.main(Trace.java:3)) – method1 calls method2; instructions for method2 are pushed onto the stack. (at Trace.method1(Trace.java:6)) – method2 throws an exception: ArrayIndexOutOfBoundsException. Because method2 doesn’t handle this exception itself, it’s passed on to the method that called it—method1. (at Trace.method2(Trace.java:10)) – method1 doesn’t define any exception handler for ArrayIndexOutOfBounds - Exception, so it hands this exception over to its calling method—main. (java.lang.ArrayIndexOutOfBoundsException: 5) – There are no exception handlers for ArrayIndexOutOfBoundsException in main. Because there are no further methods that handle ArrayIndexOutOfBoundsException, execution of the class Trace stops. Note: You can use try-catch-finally blocks to define code that doesn’t halt execution when it encounters an exceptional condition. 5/24/2017 8 What happens when exception is thrown? • Creating try-catch-finally blocks – When you work with exception handlers, you often hear the terms try, catch, and finally. Before we start to work with these concepts, let’s answer three simple questions: • Try what? First you try to execute your code. If it doesn’t execute as planned, you handle the exceptional conditions using a catch block. • Catch what? You catch the exceptional event arising from the code enclosed within the try block and handle the event by defining appropriate exception handlers. • What does finally do? Finally, you execute a set of code, in all conditions, regardless of whether the code in the try block throws any exceptions. – Following is a RiverRafting code example: 5/24/2017 class RiverRafting { void crossRapid(int degree) throws FallInRiverException { System.out.println("Cross Rapid"); if (degree > 10) throw new FallInRiverException(); } void rowRaft(String state) throws DropOarException { System.out.println("Row Raft"); if (state.equals("nervous")) throw new DropOarException(); } } 9 What happens when exception is thrown? – Test example code with exception: class TestRiverRafting { public static void main(String args[]) { RiverRafting riverRafting = new RiverRafting(); try { riverRafting.crossRapid(11);//trigger FallInRiverException //following lines will not execute if there’s exception riverRafting.rowRaft("happy"); System.out.println("Enjoy River Rafting"); } catch (FallInRiverException e1) { System.out.println("Get back in the raft"); } catch (DropOarException e2) { System.out.println("Do not panic"); } finally {//finally block must be after the catch blocks //always executes, whether there’s exception or not System.out.println("Pay for the sport"); } System.out.println("After the try block"); } } Output: Cross Rapid Get back in the raft Pay for the sport After the try block 5/24/2017 10 What happens when exception is thrown? – For a try block, you can define multiple catch blocks, but only a single finally block. Multiple catch blocks are used to handle different types of exceptions. A finally block is used to define cleanup code—code that closes and releases resources, such as file handlers and database or network connections: import java.io.*; public class MultipleExceptions { public static void main(String args[]) { FileInputStream fis = null; try { fis=new FileInputStream("file.txt");//may throw FileNotFoundException System.out.println("File Opened"); fis.read(); //may throw IOException System.out.println("Read File "); } catch (FileNotFoundException fnfe) { System.out.println("File not found"); } catch (IOException ioe) { System.out.println("File Closing Exception"); } finally { System.out.println("finally"); } System.out.println("Next task.."); } } 5/24/2017 11 What happens when exception is thrown? • Will a finally block execute even if the catch block defines a return statement? – finally block is always executed before returning to caller except when System.exit is called or JVM/OS crashed. Example: import java.io.*; public class ReturnFromCatchBlock { public static void main(String args[]) { openFile(); } private static void openFile() { FileInputStream fis = null; try { fis = new FileInputStream("file.txt"); } catch (FileNotFoundException fnfe) { System.out.println("file not found"); //finally block is executed before returning to caller (main()) return; } finally { System.out.println("finally"); } System.out.println("Next task.."); } } Output: file not found finally 5/24/2017 12 What happens when exception is thrown? • What happens if both catch and finally block define return statements? – finally block executes even if a catch block defines a return statement. For a method that defines a try-catch-finally block, what is returned to the calling method if both catch and finally return a value? Here’s an example: class MultipleReturn { int getInt() { try { String[] students = {"Harry", "Paul"}; System.out.println(students[5]);//throws exception } catch (Exception e) { return 10; } finally { return 20; } } public static void main(String args[]) { MultipleReturn var = new MultipleReturn(); System.out.println(var.getInt()); } } Output: 20 Note: If both catch and finally blocks define return statements, the calling method will receive a value 5/24/2017 from the finally block. 13 What happens when exception is thrown? • What happens if a finally block modifies the value returned from a catch block? – If a catch block returns a primitive data type, the finally block can’t modify the value being returned by it. An example: class MultipleReturn { int getInt() { int returnVal = 10; try { String[] students = {"Harry", "Paul"}; System.out.println(students[5]); } catch (Exception e) { System.out.println("About to return :" + returnVal); return returnVal; } finally { returnVal += 10; System.out.println("Return value is now :" + returnVal); } return returnVal; } public static void main(String args[]) { MultipleReturn var = new MultipleReturn(); System.out.println("In Main:" + var.getInt()); } } Output: About to return :10 Return value is now :20 In Main:10 5/24/2017 14 What happens when exception is thrown? – What happens if a catch block returns an object? An example: class MultipleReturn { StringBuilder getStringBuilder() { StringBuilder returnVal = new StringBuilder("10");//StringBuilder object try { String[] students = {"Harry", "Paul"}; System.out.println(students[5]);//throw ArrayIndexOutOfBoundsException } catch (Exception e) { System.out.println("About to return :" + returnVal); return returnVal; //returns StringBuilder object } finally { returnVal.append("10"); //modifies return object System.out.println("Return value is now :" + returnVal); } return returnVal; } public static void main(String args[]) { MultipleReturn var = new MultipleReturn(); System.out.println("In Main:" + var.getStringBuilder()); } } Output: About to return :10 Return value is now :1010 In Main:1010 Note: In this case, the catch block returns an object of the class StringBuilder. When the finally block executes, it can access the value of the object referred to by the variable returnVal and can modify it. The modified value is returned to the method main. Remember that primitives are passed by value and objects are passed by reference. 5/24/2017 15 What happens when exception is thrown? • Does the order of the exceptions caught in the catch blocks matter? – Order doesn’t matter for unrelated classes. But it does matter for related classes sharing an IS-A relationship. If you try to catch an exception of the base class before an exception of the derived class, your code will fail to compile because the exception handler for the derived class can never be reached. 5/24/2017 16 What happens when exception is thrown? • Rules to remember A try block may be followed by multiple catch blocks, and the catch blocks may be followed by a single finally block. A try block may be followed by either a catch or a finally block or both. But a finally block alone wouldn’t suffice if code in the try block throws a checked exception. In this case, you need to catch the checked exception or declare it to be thrown by your method. Otherwise your code won’t compile. The try, catch, and finally blocks can’t exist independently. The finally block can’t appear before a catch block. A finally block always executes, regardless of whether the code throws an exception. 5/24/2017 17 What happens when exception is thrown? • Can I rethrow an exception or the error I catch? – You can do whatever you want with an exception. You can rethrow it, pass it on to a method, assign it to another variable, upload it to a server, send it in an SMS, etc. Examine the following code: import java.io.*; public class ReThrowException { FileInputStream soccer; public void myMethod() { try { soccer = new FileInputStream("soccer.txt"); } catch (FileNotFoundException fnfe) { throw fnfe; } } } Compilation error: unreported exception java.io.FileNotFoundException; must be caught or declared to be thrown: throw fnfe; Note: In this case, the code neither “caught” the rethrown FileNotFoundException exception nor declared that the method myMethod would throw it using the throw clause. Hence, the code failed to compile. 5/24/2017 18 What happens when exception is thrown? – The following (modified) code declares that the method myMethod throws a FileNotFoundException, and it compiles successfully: import java.io.*; public class ReThrowException { FileInputStream soccer; public void myMethod() throws FileNotFoundException { try { soccer = new FileInputStream("soccer.txt"); } catch (FileNotFoundException fnfe) { throw fnfe; } } } Note: You can rethrow a runtime exception, but you’re not required to catch it, nor must you modify your method signature to include the throws clause. The simple reason for this rule is that RuntimeExceptions aren’t checked exceptions, and they may not be caught or declared to be thrown by your code. 5/24/2017 19 What happens when exception is thrown? • Can I declare my methods to throw a checked exception, instead of handling it? – If a method doesn’t wish to handle the checked exceptions thrown by a method it calls, it can throw these exceptions using the throws clause in its own method signature. – Examine the following example, in which the method myMethod doesn’t include an exception handler; instead, it rethrows the IOException thrown by a constructor of the class FileInputStream using the throws clause in its method signature: import java.io.*; public class ReThrowException2 { public void myMethod() throws IOException {//throws checked exception FileInputStream soccer=new FileInputStream("soccer.txt"); soccer.close(); } } Note: Any method that calls myMethod must now either catch the exception IOException or declare that it will be rethrown in its method signature. 5/24/2017 20 What happens when exception is thrown? • I can create nested loops, so can I create nested try-catch blocks too? – The simple answer is yes, you can define a try-catch-finally block within another try-catchfinally block. Theoretically, the levels of nesting for the try-catch-finally blocks have no limits. – In the following example, another set of try-catch blocks is defined in the try and finally blocks of the outer try block: 5/24/2017 import java.io.*; public class NestedTryCatch { FileInputStream players, coach; public void myMethod() { try { //Outer try block players = new FileInputStream("players.txt"); try { //Innner try block coach = new FileInputStream("coach.txt"); //.. rest of the code } catch (FileNotFoundException e) { System.out.println("coach.txt not found"); } //.. rest of the code } catch (FileNotFoundException fnfe) { //Outer catch block System.out.println("players.txt not found"); } finally { //Outer finally block try { //Another inner try block players.close(); coach.close(); } catch (IOException ioe) { System.out.println(ioe); } } } } 21 What happens when exception is thrown? – Given that players.txt exists on your system and that the assignment of players, shown in bold, doesn’t throw any exception, what is the output of the following code? import java.io.*; public class TwistInTaleNestedTryCatch { static FileInputStream players, coach; public static void main(String args[]) { try { players = new FileInputStream("players.txt"); System.out.println("players.txt found"); try { coach.close(); } catch (IOException e) { System.out.println("coach.txt not found"); } } catch (FileNotFoundException fnfe) { System.out.println("players.txt not found"); } catch (NullPointerException ne) { System.out.println("NullPointerException"); } } } 5/24/2017 a) The code prints players.txt found NullPointerException b) The code prints players.txt found coach.txt not found c) The code throws a runtime exception. d) The code fails to compile. 22 Categories of Exceptions • In this section, we’ll look at the categories of exceptions in Java, including checked exceptions, unchecked exceptions, and errors. We’ll use code examples to explain the differences between these categories. • Identifying exception categories – Checked exceptions (commonly handled in code) – Runtime exceptions (unchecked exceptions) (normally not handled in code) – Errors (thrown by JVM) 5/24/2017 23 Categories of Exceptions • Checked exceptions – When we talk about handling exceptions, it’s checked exceptions that take up most of our attention. What is a checked exception? • A checked exception is an unacceptable condition foreseen by the author of a method but outside the immediate control of the code. For example, FileNotFoundException is a checked exception. This exception is thrown if the file that the code is trying to access can’t be found. When it’s thrown, this condition is outside the immediate control of the author of the code but it was foreseen by the author. • A checked exception is a subclass of class java.lang.Exception, but it’s not a subclass of java.lang.RuntimeException. It’s interesting to note, however, that the class java.lang.RuntimeException itself is a subclass of the class java.lang.Exception. – If a method uses another method that may throw a checked exception, one of the two following things should be true: • The method should be enclosed within a try-catch block. OR • The method should specify this exception to be thrown in its method signature 5/24/2017 24 Categories of Exceptions • Runtime exceptions (also known as unchecked exceptions) – Although you’ll spend most of your time and energy combating checked exceptions, it’s the runtime exceptions that’ll give you the most headaches. This is particularly true when you’re preparing to work on real-life projects. Some examples of runtime exceptions are NullPointerException (the most common one), ArrayIndexOutOfBoundsException, and ClassCastException. What is a runtime exception? • A runtime exception is a representation of a programming error. These occur from inappropriate use of another piece of code. For example, NullPointerException is a runtime exception that occurs when a piece of code tries to execute some code on a variable that hasn’t been assigned an object and points to null. Another example is ArrayIndexOutOfBoundsException, which is thrown when a piece of code tries to access an array list element at a nonexistent position. • A runtime exception is a subclass of java.lang.RuntimeException. • A runtime exception may not be a part of the method signature, even if a method may throw it. 5/24/2017 25 Categories of Exceptions – Examine the following code, which throws a runtime exception (ArrayIndexOutOfBoundsException): public class InvalidArrayAccess { public static void main(String args[]) { String[] students = {"Shreya", "Joseph"}; System.out.println(students[5]); //throws runtime exception System.out.println("All seems to be well"); } } – Previous code with runtime exception handling: public class InvalidArrayAccess { public static void main(String args[]) { String[] students = {"Shreya", "Joseph"}; try { System.out.println(students[5]); } catch (ArrayIndexOutOfBoundsException e){ System.out.println("Exception"); } System.out.println("All seems to be well"); } } The output is as follows: Exception All seems to be well 5/24/2017 26 Categories of Exceptions • Errors – Java errors are considered to be serious exceptional conditions and they can’t be directly controlled by your code. • What’s an error? – An error is a serious exception thrown by the JVM as a result of an error in the environment state that processes your code. For example, NoClassDefFoundError is an error thrown by the JVM when it’s unable to locate the .class file that it’s supposed to run. StackOverflowError is another error thrown by the JVM when the size of the memory required by the stack of a Java program is greater than what the JRE has offered for the Java application. This error usually occurs as a result of infinite or highly nested loops. – An error is a subclass of class java.lang.Error. – An error need not be a part of a method signature. – An error can be caught by an exception handler, but it shouldn’t be. 5/24/2017 27 Categories of Exceptions – The following example shows how it’s possible to “catch” an error: public class CatchError { public static void main(String args[]) { try { myMethod(); } catch (StackOverflowError s) { System.out.println(s); //handles error exception } } public static void myMethod() { System.out.println("myMethod"); myMethod(); } } Note: A class can catch and handle an error, but it shouldn’t—it should instead let the JVM handle the error itself. 5/24/2017 28 Common exception classes and categories • In this section, we’ll take a look at common exception classes and categories of exceptions. We’ll look at the scenarios in which these exceptions are thrown and how to handle them. For the Java Programmer I exam, you should be familiar with the scenarios that lead to these commonly thrown exception classes and categories, and how to handle them. Listed below are common exceptions and errors. Runtime Exceptions Errors ArrayIndexOutOfBoundsException ExceptionInInitializerError IndexOutOfBoundsException StackOverflowError ClassCastException NoClassDefFoundError IllegalArgumentException OutOfMemoryError IllegalStateException NullPointerException NumberFormatException 5/24/2017 29 Common exception classes and categories • ArrayIndexOutOfBoundsException and IndexOutOfBoundsException – They are runtime exceptions, which share an IS-A relationship. IndexOutOfBoundsException is subclassed by ArrayIndexOutOfBoundsException. ArrayIndexOutOfBoundsException is thrown when a piece of code tries to access an array out of its bounds (either an array is accessed at a position less than 0 or at a position greater than or equal to its length). IndexOutOfBoundsException is thrown when a piece of code tries to access a list, like an ArrayList, using an illegal index. Its class hierarchy is as follows: java.lang.Throwable<-java.lang.Exception<-java.lang.RuntimeException<java.lang.IndexOutOfBoundsException<-java.lang.ArrayIndexOutOfBoundsException – Assuming that an array and list have been defined as follows: String[] season = {"Spring", "Summer"}; ArrayList<String> exams = new ArrayList<>(); exams.add("SCJP"); exams.add("SCWCD"); //Following lines of code will throw ArrayIndexOutOfBoundsException: System.out.println(season[5]);//Can’t access position >= array length System.out.println(season[-9]);//Can’t access at negative position //Following lines of code will throw IndexOutOfBoundsException: System.out.println(exams.get(-1));//Can’t access list position < 0 System.out.println(exams.get(4));//Can’t access position >= list length 5/24/2017 30 Common exception classes and categories • ClassCastException – Class hierarchy of ClassCastException: java.lang.Throwable<-java.lang.Exception<-java.lang.RuntimeException<java.lang.ClassCastException – Example of ClassCastException as shown in bold: import java.util.ArrayList; public class ListAccess { public static void main(String args[]) { ArrayList<Ink> inks = new ArrayList<Ink>(); inks.add(new ColorInk()); inks.add(new BlackInk()); Ink ink = (BlackInk)inks.get(0);//Throws ClassCastException } } class Ink{} class ColorInk extends Ink{} class BlackInk extends Ink{} Note: This line of code avoided the compilation error because the variable inks defines an ArrayList of type Ink, which is capable of storing objects of type Ink and all its subclasses. The code then correctly adds the allowed objects: one each of BlackInk and ColorInk. 5/24/2017 31 Common exception classes and categories – If the code had defined an ArrayList of type BlackInk or ColorInk, the code would have failed the compilation, as follows: import java.util.ArrayList; public class Invalid { public static void main(String args[]) { ArrayList<ColorInk> inks = new ArrayList<ColorInk>(); inks.add(new ColorInk()); Ink ink = (BlackInk)inks.get(0);//Compilation error } } class Ink{} class ColorInk extends Ink{} class BlackInk extends Ink{} Here’s the compilation error thrown by the previously modified piece of code: Invalid.java:6: inconvertible types found : ColorInk required: BlackInk Ink ink = (BlackInk)inks.get(0); 5/24/2017 32 Common exception classes and categories – You can use the instanceof operator to verify whether an object can be cast to another class before casting it. Assuming that the definition of classes Ink, ColorInk, and BlackInk are the same as defined in the previous example, the following lines of code will avoid the ClassCastException: import java.util.ArrayList; public class AvoidClassCastException { public static void main(String args[]) { ArrayList<Ink> inks = new ArrayList<Ink>(); inks.add(new ColorInk()); inks.add(new BlackInk()); if (inks.get(0) instanceof BlackInk) { BlackInk ink=(BlackInk)inks.get(0);//No ClassCastException } } } Note: In the above example, the condition (inks.get(0) instanceof BlackInk) evaluates to false, so the then part of the if statement doesn’t execute. 5/24/2017 33 Common exception classes and categories • IllegalArgumentException – It is thrown to specify that a method has passed illegal or inappropriate arguments. Its class hierarchy is as follows: java.lang.Throwable<-java.lang.Exception<-java.lang.RuntimeException<java.lang.IllegalArgumentException – Even though it’s a runtime exception, programmers usually use this exception to validate the arguments that are passed to a method. The exception constructor is passed a descriptive message, specifying the exception details. Examine the following code: public void login(String username, String pwd, int maxLoginAttempt) { if (username == null || username.length() < 6) throw new IllegalArgumentException ("Login:username can’t be shorter than 6 chars"); if (pwd == null || pwd.length() < 8) throw new IllegalArgumentException ("Login: pwd cannot be shorter than 8 chars"); if (maxLoginAttempt < 0) throw new IllegalArgumentException ("Login: Invalid loginattempt val"); //.. rest of the method code } Note: The above method validates the various method parameters passed to it and throws an appropriate IllegalArgumentException if they don’t meet the requirements of the method. Each object of the IllegalArgumentException is passed a different String message that briefly 5/24/2017 34 describes it. Common exception classes and categories • IllegalStateException – According to the Java API documentation, an IllegalStateException “signals that a method has been invoked at an illegal or inappropriate time. In other words, the Java environment or Java application is not in an appropriate state for the requested operation.” Its class hierarchy is as follows: java.lang.Throwable<-java.lang.Exception<-java.lang.RuntimeException<java.lang.IllegalStateException – 5/24/2017 A Java program can throw IllegalStateException to signal to the calling method that the method being requested for execution can’t be called for the current state of an object. For example, what happens if an application tries to modify an SMS that is already in transmission? Examine the following code: class SMS { private String msg; private boolean inTransit = false; public void create() { msg = "A new Message"; } public void transmit() { ........ //Code to transmit message inTransit = true; } public void modify() { if (!inTransit) msg = "new modified message"; else throw new IllegalStateException("Msg in transit. Can't modify it"); } } public class ThrowIllegalStateException { public static void main(String[] args) { SMS sms = new SMS(); sms.create(); sms.transmit(); sms.modify(); } } 35 Common exception classes and categories • NullPointerException – This is the quintessential exception. Most likely, almost all Java programmers have encountered this exception. Its class hierarchy is as follows: java.lang.Throwable<-java.lang.Exception<-java.lang.RuntimeException<java.lang.NullPointerException – This exception is thrown by the JVM if you try to access a method or a variable with a null value. The exam can have interesting code combinations to test you on whether a particular piece of code will throw a NullPointerException. The key is to ensure that the reference variable has been assigned a non-null value. In particular, we’ll look at the following cases: • Accessing members of a reference variable that is explicitly assigned a null value. • Accessing members of an uninitialized instance or static reference variable. These are implicitly assigned a null value. • Using an uninitialized local variable, which may seem to throw a NullPointerException. • Attempting to access nonexistent array positions. • Using members of an array element that are assigned a null value. – Let’s look at the first case, in which a variable is explicitly assigned a null value: 5/24/2017 import java.util.ArrayList; class ThrowNullPointerException { static ArrayList<String> list = null; //List is null public static void main(String[] args) { list.add("1"); //Throws NullPointerException } } 36 Common exception classes and categories – By default, the static and instance variables of a class are assigned a null value. In the previous example, the static variable list is assigned an explicit null value. When the method main tries to execute the method add on variable list, it calls a method on a null value. This call causes the JVM to throw a NullPointerException (which is a RuntimeException). If you define the variable list as an instance variable and don’t assign an explicit value to it, you’ll get the same result (NullPointerException being thrown at runtime). Because the static method main can’t access the instance variable list, you’ll need to create an object of class ThrowNullPointerException to access it: import java.util.ArrayList; class ThrowNullPointerException { ArrayList<String> list;//list is implicitly assigned null value public static void main(String[] args) { ThrowNullPointerException obj = new ThrowNullPointerException(); obj.list.add("1");//Throws NullPointerException since list is null } } – What happens if we modify the previous code as follows? Will it still throw a NullPointerException? 5/24/2017 import java.util.ArrayList; class ThrowNullPointerException { public static void main(String[] args) { ArrayList<String> list; //Local variables aren’t initialized if (list!=null) list.add("1"); //Fails to compile because list is uninitialized } } 37 Common exception classes and categories – Another set of conditions when code may throw the NullPointerException involves use of arrays: class ThrowAnotherNullPointerException { static String[] oldLaptops;//assigned null value by default public static void main(String[] args) { System.out.println(oldLaptops[1]);//Throws NullPointerException String[] newLaptops = new String[2]; System.out.println(newLaptops[1].toString());//Throws exception } } Note: The variable oldLaptops is assigned a null value by default because it’s a static variable. Its array elements are neither initialized nor assigned a value. The code that tries to access the array’s second element throws a NullPointerException. In the second case, two array elements of the variable newLaptops are initialized and assigned a default value of null. If you call method toString on the second element of variable newLaptops, it results in a NullPointerException being thrown. – If we modify that line as shown in the following code, it won’t throw an exception—it’ll print the value null: System.out.println(newLaptops[1]); //Prints "null". 5/24/2017 38 Common exception classes and categories • NumberFormatException – This is a runtime exception. It’s thrown to indicate that the application has tried to convert a string (with an inappropriate format) to one of the numeric types. Its class hierarchy is as follows: java.lang.Throwable<-java.lang.Exception<-java.lang.RuntimeException<java.lang.IllegalArgumentException<-java.lang.NumberFormatException – Multiple classes in the Java API define parsing methods. One of the most frequently used methods is parseInt from the class Integer. It’s used to parse a String argument as a signed (negative or positive) decimal integer. Here are some examples: System.out.println(Integer.parseInt("-123")); System.out.println(Integer.parseInt("123")); System.out.println(Integer.parseInt("+123")); System.out.println(Integer.parseInt("123_45")); //Throws NumberFormatException System.out.println(Integer.parseInt("12ABCD")); //Throws NumberFormatException Note: Starting in Java 7, you can use underscores (_) in numeric literal values. But you can’t use them in String values passed to the method parseInt. The letters ABCD are not used in the decimal number system, but they can be used in the hexadecimal number system, so you can convert the hexadecimal literal value "12ABCD" to the decimal number system by specifying the base of the number system as 16: System.out.println(Integer.parseInt("123ABCD", 16)); //Prints 1223629 5/24/2017 39 Common exception classes and categories – The following is an example of code that rethrows NumberFormatException programmatically: public class ThrowNumberFormatException { public static int convertToNum(String val) { int num = 0; try { num = Integer.parseInt(val, 16); } catch (NumberFormatException e) { throw new NumberFormatException(val+ " cannot be converted to hexadecimal number"); } return num; } public static void main(String args[]) { System.out.println(convertToNum("16b")); //Rethrows NumberFormatException thrown by parseInt with new message System.out.println(convertToNum("65v")); } } 5/24/2017 Output: 363 Exception in thread "main" java.lang.NumberFormatException: 65v cannot be converted to hexadecimal number at ThrowNumberFormatException.convertToNum(ThrowNumberFormatException.java:8) at ThrowNumberFormatException.main(ThrowNumberFormatException.java:14) 40 Common exception classes and categories • ExceptionInInitializerError – This error is typically thrown by the JVM when a static initializer in your code throws any type of RuntimeException. Its class hierarchy is as follows: java.lang.Throwable<-java.lang.Error<-java.lang.LinkageError<java.lang.ExceptionInInitializerError – A static initializer block is defined using the keyword static, followed by curly braces, in a class. This block is defined within a class, but not within a method. It’s usually used to execute code when a class loads for the first time. Runtime exceptions arising from any of the following will throw this error: • • • Execution of an anonymous static block Initialization of a static variable Execution of a static method (called from either of the previous two items) – The anonymous static initializer block of the class defined in the following example will throw a NumberFormatException, and when the JVM tries to load this class, it’ll throw an ExceptionInInitializerError: 5/24/2017 public class DemoExceptionInInitializerError { static { int num = Integer.parseInt("sd", 16); } } Output: java.lang.ExceptionInInitializerError Caused by: java.lang.NumberFormatException: For input string: "sd" at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48) at java.lang.Integer.parseInt(Integer.java:447) at DemoExceptionInInitializerError.<clinit>(DemoExceptionInInitializerError.java:3) 41 Common exception classes and categories – In the following example, initialization of a static variable results in a NullPointerException being thrown. When this class is loaded by the JVM, it throws an ExceptionInInitializerError: public class DemoExceptionInInitializerError1 { static String name = null; static int nameLength = name.length(); } Output: java.lang.ExceptionInInitializerError Caused by: java.lang.NullPointerException at DemoExceptionInInitializerError1.<clinit>(DemoExceptionInInitializerError1.java:3) Exception in thread "main" – Now let’s move on to the exception thrown by a static method, which may be called by the static initializer block or to initialize a static variable. Examine the following code, in which MyException is a user-defined RuntimeException: public class DemoExceptionInInitializerError2 { static String name = getName(); static String getName() { throw new MyException(); } } class MyException extends RuntimeException{} Output: 5/24/2017 java.lang.ExceptionInInitializerError Caused by: MyException at DemoExceptionInInitializerError2.getName(DemoExceptionInInitializerError2.java:4) at DemoExceptionInInitializerError2.<clinit>(DemoExceptionInInitializerError2.java:2) 42 Common exception classes and categories • StackOverflowError – This error extends VirtualMachineError. As its name suggests, it should be left to be managed by the JVM. Its class hierarchy is as follows: java.lang.Throwable<-java.lang.Error<-java.lang.VirtualMachineError<java.lang.StackOverflowError – This error is thrown by the JVM when a Java program calls itself so many times that the memory stack allocated to execute the Java program “overflows.” Examine the following code, in which a method calls itself recursively without an exit condition: public class DemoStackOverflowError{ static void recursion() { recursion(); } public static void main(String args[]) { recursion(); } } The following error is thrown by the previous code: Exception in thread "main" java.lang.StackOverflowError at DemoStackOverflowError.recursion(DemoStackOverflowError.java:3) 5/24/2017 43 Common exception classes and categories • NoClassDefFoundError – What would happen if you failed to set your classpath and, as a result, the JVM was unable to load the class that you wanted to access or execute? Or what happens if you try to run your application before compiling it? In both these conditions, the JVM would throw NoClassDefFoundError. Its class hierarchy is as follows: java.lang.Throwable<-java.lang.Error<-java.lang.LinkageError<java.lang.NoClassDefFoundError – This error is thrown if the Java Virtual Machine or a ClassLoader instance tries to load in the definition of a class (as part of a normal method call or as part of creating a new instance using the new expression) and no definition of the class could be found. Because this particular error is not a coding issue, it is a linkage error arising from a missing class file definition at runtime. This error should not be handled by the code and should be left to be handled exclusively by the JVM. 5/24/2017 44 Common exception classes and categories • OutOfMemoryError – What happens if you create and use a lot of objects in your application? For example, if you load a large chunk of persistent data to be processed by your application. In such a case, the JVM may run out of memory on the heap, and the garbage collector may not be able to free more memory for the JVM. When the JVM is unable to create any more objects on the heap, an OutOfMemoryError will be thrown. Its class hierarchy is as follows: java.lang.Throwable<-java.lang.Error<-java.lang.VirtualMachineError<java.lang.OutOfMemoryError Note: You’ll always work with a finite heap size, no matter what platform you work on, so you can’t create and use an unlimited number of objects in your application. To get around this error, you need to either limit the number of resources or objects that your application creates or increase the heap size on the platform you’re working with. A number of tools are available (which are beyond the scope of this book) that can help you monitor the number of objects created in your application. 5/24/2017 45