CS62 - Fall 2026 - Class 5

Example code in this lecture

   GuessingGame
   GradeGenerator
   GenericsExamples

Lecture notes

  • admin
       - assignment 1 returned
       - Assignment 3: Darwin
          - two week assignment
             - some classes graded after week 1
             - remaining graded after week 2
          - partnered assignment (if you want)
       - lab tomorrow

  • ArrayLists
       - Arrays are of fixed length and are built into the language
       - ArrayLists are built on top of arrays (underneath the covers, they are implemented using arrays), but they allow much more functionality than arrays
          - they are much more similar to lists in python

       - ArrayLists are a class, so to use them you create them by calling the constructor and then interact with them via methods

       - Constructing a new ArrayList
          ArrayList<type_of_items> name = new ArrayList<type_of_items>();

          e.g.,

          ArrayList<Card> cards = new ArrayList<Card>();

          - This is calling the constructor with a bit of information about what type of thing we're going to be storing in the ArrayList

       - ArrayLists have many methods, the most common we'll use now are:
          - size()
             - how many things are in the ArrayList
          - get(index)
             - get the value at index (will be of whatever type the ArrayList was initialized as)

          - set(index, value)
             - set entry at index to value. index must be between 0 and size()-1 and the value must be of the type that was initialized.

          - add(value)
             - add the value to the end of the ArrayList and increase the size by 1
             - this is something we couldn't do easily with arrays!


  • run GuessingGameWithProblem in GuessingGame code

  • look at GuessingGameWithProblem in GuessingGame code
       - Is there anything that the user could do while playing the game to cause a problem?
          - if the user enters something that is not a number!
       - What do you think happens when the user enters something that is not a number?
          - We get an Exception!

  • Exceptions
       - What exceptions have you seen already?
          - NullPointerException
          - ArrayIndexOutOfBoundsException
          - StringIndexOutOfBoundsException
       - Exceptions may seem like errors (and they are), but they're also another way for a method to communicate to whoever calls it
          - return allows it to return a value
          - throwing an Exception tells whoever called the method that something went wrong

  • try-catch blocks
       - If you want a program to stop when an Exception is thrown, you don't have to do anything (as you've noticed)
       - If you want to try and handle a problem and NOT have the program stop, you can "catch" an Exception
       - Syntax:

          try{
             // code that might throw an Exception
          } catch (exception_class_name variable_name){
             // code to run if an exception of type exception_class_name occurs in the try block above
          }

       - When the code is run, if no Exception occurs, then the catch block is skipped
       - If an Exception of the type exception_class_name occurs in the try block of code, then the code jumps immediately down to catch block, executes the code in there and then continues on after the block

  • Can we use this to help us solve our problem with the guessing game?

  • Look at GuessingGame in GuessingGame code
       - We've surrounded the part of the code that handles the input and response with a try-catch block
       - If the user enters a number, everything works as before
       - If the user enters something that is not a number, then the in.nextInt() call will throw an Exception
          - It will skip the if/else if/else block of code and go immediately to the catch block
          - It will then print out that there was an issue
          - The scanner class buffers the input and so it still has that string sitting there. We have to read the string and ignore it.
          - The loop will then continue as normal

  • Reading from files
       - There are many ways to read data from files (we'll see 2 today)
       - One is to use the Scanner class

          Given a String with a filename:

          Scanner in = new Scanner(new File(filename));

       - Same Scanner class/interface we were using before except now we created it to read from a file instead of from System.in (from the user)

  • Checked Exceptions
       - Could anything go wrong when opening a file like this? Put another way, what Exceptions could occur?
       - If you just try and open the scanner like this, Java will complain
       - Some Exceptions are called "checked" Exceptions
          - checked Exceptions MUST be handled
          - we must wrap the statement that could throw that Exception in a try-catch block

  • If you try and do the above line for creating a Scanner from a file, you'll get a compilation error
          "Unhandled Exception"
       - Opening a file can generate a FileNotFoundException which is a checked exception, so we have to put it in a try-catch block

  • look at GradeGeneratorPrint in GradeGenerator code

  • Writing to files
       - Printing the grades list is nice, but in some situations it would be better to print it to a file
       - As with reading from files, there are many ways to do it
       - One easy way is with the PrintWriter class

          PrintWriter out = new PrintWriter(new FileOutputStream(outfilename));

       - PrintWriter has a similar interface to the System.out, in particular, it has a method called out.println()
          - the difference is that it prints it out to the file
       - When you're done writing to a file, *** don't forget to close it ***
       - Do you think opening a file for writing throws any Exceptions?
          - Yes! FileNotFoundException

  • run and look at GradeGeneratorFile in GradeGenerator code
       - looks almost the same, except we create a PrintWriter and use that instead of System.out
       - Why do I only have one try-catch block?
          - the catch statement will catch *any* Exception of that type in the try block
       - What's different about the code in the catch statement?
          - Before, there was only one file that could be the offending file being opened
          - Now, it could be either the file being read from or the file being written to

  • Exceptions are classes!
       - they have methods, etc.
       - When an exception is thrown/generated, a new exception object is generated
       - The two most common methods you might want to call is:
          - e.getMessage()
             - get (as a String) a detailed messaged about this exception
          - e.printStackTrace()
             - prints out the normal thing you see with the hierarchy of method calls that led to the exception being thrown

  • Look at GradeGeneratorFileBufferedReader
       - BufferedReader is another class that allows us to read from files (well, really the FileReader class)
       - It has less bells and whistles than the scanner class
          - it doesn't support things like nextInt, nextFloat, etc.
       - the most common method that you'll call is readLine(), which reads the next line of the file and returns it as a String
       - when the file is out of data, this method returns null
       - so the general form of a loop is something like:

          read a line

          while that line isn't null
             do some stuff

             read another line

  • IOException
       - When you open a FileReader(i.e. BufferedReader) it can throw a FileNotFoundException
       - When you read from a BufferedReader it can throw an IOException, which is a type of Exception
       - I've only caught the IOException. Why is Java letting me do this?
          - IOException is a superclass of FileNotFoundException!

  • Exception hierarchy
       - There are a lot of Exceptions!
       - All Exceptions, inherit from the class Exception
          - it's kind of like Object for Exceptions (though remember that Exceptions are classes and actually do inherit from Object)
       - If you put:

          catch(Exception e){

          }

          - you will catch *ALL* exceptions that are thrown!
          - however, it's better style to specifically list the Exception you're trying to catch

  • Look at GradeGeneratorFileBufferedReader2
       - sometimes it may make sense to open the BufferedReader or the PrintWriter somewhere else and then pass it as a parameter

  • Generics
       - We can write our own classes that use generics!
       - Look at Container class in GenericsExamples code
          - We can specify one or my type variables in the class header inside < >
             public class Container<V>{
       
             }

             - by convention, we use a single uppercase letter to indicate a type variable
          - You can then use this variable anywhere in your program where a type would be used
             - private V value;
             - public Container(V value)
             - public V getValue()
             - public void setValue(V newValue)
       - When you instantiate this class you should specify a type parameter
          Container<Integer> c = new Container<Integer>();
          int val = c.getValue();

          or

          Container<String> c = new Container<String>();
          String val = c.getValue();

          - For example, we could add the main:

             Container<String> c1 = new Container<String>("banana");
             Container<Integer> c2 = new Container<Integer>(10);
          
             System.out.println(c1.getValue());
             System.out.println(c2.getValue());
          
             // c2.setValue("car"); // DOESN'T WORK!

       - How can we return multiple objects/data types from a method in java?
          - The bad way: public void Object[] method()
          - The good way: implement a Pair class using generics

       - implement a class called Pair that supports generics for 2 types
          - if you need more than one type variable, you can introduce another one and comma separate
          - What methods should the class contain?
          - Constructor(s)?
          - private instance variables?
          - methods?

       - look at the Pair class in the GenericsExamples code

  • this(...)
       - We'll often have multiple constructors in a class. Why?
          - Allow for different ways of creating the object
          - Often, allow for having versions that specify more details

       - It can be convenient in these cases to call one of the constructors from another constructor
          - there's a special syntax to do this because we can just say new ..., since that would create a whole new instance of the class

       - Look at the Matrix class from Darwin
          - We have two constructors
          - The first one simply calls the second one with the default parameters

       - the "this" call (like a super call), must be the first line in the constructor

  • char
       - one of the other built in types for representing a single character
       - to create them use single quotes
          char c = 'a';

       - returned by some of the String methods, e.g.
          String s = "...";
          char first = s.charAt(0);

  • type casting
       - If we have a class B extends A, is the following legal?
          A varA = new B(...);

          - yes, we can always assign a subclass to a variable of the type of a parent class

       - Could we then do the following?
          B varB = varA;

          - No! Even though in this case we know that there is a B in varA, the Java compiler cannot be sure in all cases

       - However, sometimes we (as the programmer) know the contents. We can tell Java that we know the type and to cast (interpret) the value as that type.
       - The way to do that is with parentheses and the type:

          B varB = (B)varA

       - We can also do this with some of the built-in types:
          double y = 5.5;
          int x = (int)y;

          - Note that this will truncate the decimal part.

       - We can also use type casting to force Java to do floating point division rather than integer division
          - The WRONG way:
          int x = 9;
          int y = 2;
          double z = x/y;

          - The right way
          int x = 9;
          int y = 2;
          double z = ((double)x)/y;