Exceptions:

  • Short for exceptional event
    • Disrupts the normal flow of events
  • Is actually an object that is thrown after an errors occurs
  • Thrown at runtime
  • List of some Java exception classes:
    • NullPointerException
    • ArrayIndexOutOfBoundsException
    • StringIndexOutOfBoundsException
    • ArithmeticException
    • ClassCastException
    • IllegalArgumentException

Throwing an Exception:

  • When an error occurs the throwFor() method is called
  • It then creates an instance of the proper exception class
  • Finally, it uses the throw operator to give the object to the JVM

The Call Stack:

General Information:

  • Can be called either call stack trace or just stack trace
    • The “stack” part of stack trace: Represents how method calls are internally managed by the JVM
    • The “trace” part of stack trace: A list of method calls before the exception was thrown
  • Read from bottom up

JVM Process

  • JVM must store info about the state of the method it is running
    • Saves value of a method’s local variables
    • Saves a reference to the next instruction to execute once the JVM switches back to the method
  • Once the called method is returned, the JVM retrieves the saved state of the calling method and continues
    • Moves back up the method call hierarchy (Similar to how recursion works)
  • Uses a stack-based data structure to store info
    • The bottom of the stack is main and other method info are added to the top of the stack
    • Once a method is complete, it is popped off of the stack
    • When main is popped of the stack, the program ends

The Throwable Hierarchy:

  • There is a hierarchy of exception types
    • Throwable is at the top of the Hierarchy
    • Sister classes Error and Exception are below Hierarchy of Exceptions

Error vs Exception Classes:

  • Error subclasses are often errors that can’t be recovered from
    • Ex. JVM no longer has any memory to run the program
  • Exceptions give more flexibility in how they can be handled

Handling Exceptions by Catching:

  • A way to catch an exception and run a block of code in response
    • Allows for the separation of actual program code from error handling
    • Makes code less confusing to read and write
  • Done through a try-catch block
    • Try: Attempts to run a block of code
    • Catch: Catches the thrown exception and runs a block of code in response
      • Has a parameter that represents the exception type
      • Only runs if the exception matches the parameter exception type
      • Multiple catch blocks can be used to catch multiple types of errors
      • Can combine catch blocks together if their handling steps are the same
  • Finally block:
    • Can be added to the end of a try-catch block
    • Always runs a block of code after try-catch
  • Useful Instance methods of Throwable Objects:
    • getMessage(): Returns details of exception
    • printStackTrace(): Prints the stack trace of the exception
try {
  //Code that attempts to run
} catch (ExceptionType identifier) {
  //Code that runs if ExceptionType is thrown
} catch (ExceptionType2 identifier) {
    //Code that runs if ExceptionType2 is thrown
} catch (ExceptionType3 || ExceptionType4) {
    //Code that runs if ExceptionType3 or 4 is thrown
} finally {
  //Code to run at the end of try-catch block
}

File I/O and the FileNotFoundException

WARNING

Check for null before calling any methods on an object

  • The java.io.File class is used to interact with files in Java
  • With the Scanner class, you can read the data of a file
    • Will throw a FileNotFoundException if the Scanner attempts to read a non-existent file
  • Every time an enter or return key is inserted into a text file, it inputs a newline character into the file
    • This newline character determines where each line starts and ends in a file
  • The java.io.PrintWriter class is used to print out data to a file
import java.io.File;
import java.io.PrintWriter;
import java.util.Scanner;
 
File fileIn = new File(inputFileName); //Creating a new File object to interact with the file
File fileOut = new File(outputFileName); //File object for output file
Scanner fileScan = new Scanner(fileIn); //Takes a File object as a parameter
PrintWriter filePrint = new PrintWriter(fileOut); //Takes a File object as a parameter
 
String line = fileScan.nextLine(); //Saving line of input file to a String
filePrint.println(line + "hi"); //Printing to output file
 
//Do null checks for both before closing
fileScan.close();
filePrint.close();

Declaring Exceptions to be Thrown (Removing try-catch requirement):

  • Unlike ArrayIndexOutOfBoundsExceptions, Arithmetic and InputMismatch exceptions you can’t write code that might throw an exception without doing something in case it occurs
    • Must either catch or declare the exception
  • Declaring an exception doesn’t handle it
//Add throws followed by the exception name to declare an exception
public static void main(String[] args) throws ExceptionName {
 
}

Checked vs Unchecked Exceptions:

  • Unchecked Exceptions: Exceptions that aren’t caught or declared
    • This is done for very common exceptions that can happen in many different areas of our code
    • It would be cumbersome and inefficient to catch/declare each one
    • Ex. The RuntimeException class and its subclasses
  • Checked Exceptions: Exceptions that must be caught or declared
    • More uncommon than unchecked exceptions
    • Ex. The IOException class and its subclasses

Defining an Exception and Using the Throw Operator:

  • To write an exception, simply extend the exception class or any of its descendants
  • Allows for the creation of more custom and specific exceptions
public class ExceptionName extends ParentExceptionName {
  //Constructor
  public ExceptionName {
    //Code to run when the exception is triggered
  }
}
  • You can use an if-statement and the throw operator to throw an error based off a condition
if (conditon) {
  throw new ExceptionName;
}

Delimited Files:

  • Files that store structured data in a persistent manner
    • CSVs (Comma Separated Values)
  • We can use CSVs to store data that is persistent across multiple runs of a program using PrintWriter
    • Must place commas in the correct locations between data
  • The String.split() method can be used to split a String and store its values in an array
    • You can use a regular expression to have multiple delimiters from which you can split from
String[] arrayName = stringName.split(delimiter); //Singular Delimiter
String[] arrayName = stringName.split("[A-Z]+"); //Example of using a regular expression (Will split from any capital letter)
  • Scanners can also be used to parse delimited Strings
Scanner ScannerName = new Scanner(FileObject);
Scanner ScannerName2 = new Scanner(ScannerName.nextLine());
ScannerName2.useDelimiter(delimiter);
ScannerName2.nextInt(); //Example
ScannerName2.nextDouble(); //Example