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;