CS62 - Spring 2020 - Class 5

Example code in this lecture

   GuessingGame
   GradeGenerator
   GenericsExamples

Lecture notes

  • admin
       - quiz returned
       - assignment 1: how'd it go?
       - lab tomorrow
          - first half, some experimentation
          - second half, start the assignment

  • 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 to 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 while loop code 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 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

  • 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

  • Object class
       - I've said that all classes have a toString method and an equals method
          - what are their default behaviors?
             - toString: the class name@memory location
             - equals: return true only if they are exactly the same object (i.e., equivalent to using ==)

       - We can write out own to change the behavior for a particular class

       - Where do you think these default methods come from?
          - we inherit them!

       - If we do now specify a parent (i.e., extends), then by default we extend a class called Object
          - we either implicitly extend Object
          - or, we extend something that somewhere along the parents extends Object (either implicitly or explicitly)

       - What type of classes could we store in a variable of type Object? I.e.,
          Object o = ?

          - Anything!

  • the Java class hierarchy
       - *everything* in Java is a subclass of some class (except for 1 class in Java)
       - you can only inherit from one class
       - if you don't inherit from a class, by default, you inherit from the class Object
       - You can see the object hierarchy at: http://docs.oracle.com/javase/7/docs/api/overview-tree.html

  • Generics
       - Recall from our discussion of ArrayList that we can instantiate an ArrayList to hold any type of Object
          - For example, we can have ArrayLists of many different types:
             ArrayList<Integer> nums = new ArrayList<Integer>();
             ArrayList<String> strings = new ArrayList<String>();

       - The reason we can do this all called "generics"
          - generics weren't always a part of Java
          - Before generics, we had to make a choice between:
             - Defining one class for every type we wanted to use it for, e.g. ArrayListInteger
                - this allowed Java to ensure that the methods like get and set returned/took as parameters appropriate types
                - the downside is we had to create one class for every type!
             - Defining a single class that used Object
                - get would return and Object and you would have to type cast it, e.g.:
                   ArrayList list = new ArrayList();
                   list.add("banana");
                   String val = (String)list.get(0)
                - We only have to write one class, but we have to type case a lot and we lose the type checking that goes along with that

       - If you look at the documentation for ArrayLists, you can see that they have a generic type argument, E:
          https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html

          - The "type variable" E, is used anywhere that a type would be expected
          
       - 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

  • ArrayLists
       - Java has a List interface for data structures that store data sequentially:
          - https://docs.oracle.com/javase/8/docs/api/java/util/List.html
          - lots of methods, but key: get and set and particular indices

       - The ArrayList class implements this interface
       
       - Why do you think its called "ArrayList"?
          - the underlying structure that it stores the data in is an array

       - what was the main functionality that ArrayLists added over arrays?
          - add/extend

       - how do you think this is done?