CMSI 2120: Welcome to Week 02

This Week's Agenda

For this week, here's the plan, Fran…

Let's Get GOING!!

We'll start off the week by looking at a couple of textbook chapters and glean some good information from them. We'll look at data structures, data storage, object-oriented programming, and a few top-level ideas from software engineering. Then on Wednesday we'll delve into Dr. Toal's data structures page and follow up with getting to know the details of Java programming, starting on the Java bootcamp page.

Classes and Objects in Java

What is a class? In Java, as in many other languages, a class is a way of defining a type of a thing, in some sort of general sense. For example, think of an automobile. Your typical car has quite a few things that are parts of it: the steering wheel, the seats, the tires, the motor, the hood ornament, doors, windshield, and so on. Yet when you think about it, ALL cars [except for a few odd examples] have these things. So, defining a class car defines some sort of a thing that has all these parts. You could think of a class as a sort of template or cookie cutter which can be used to make lots of those items – a car class can be used to make LOTS of car objects.

The next part of this, of course, is using the class to make the objects. This is a process known as instantiation, and the things that are created in this way are known as objects [duh]. They can also be thought of [and called] instances of the class, which is where the term instantiation comes from, of course.

Here is a quick example of a Java class file, just to make sure we're adults:

   /**
    * sample class file
    */
    public class FlyingDonkey extends Pteradactyl implements Imaginary {
       private static final double altitudeInFeet = 36000.123;
       private static final int    numberOfWings  = 4;
       private String name = "Esmerelda";

       public FlyingDonkey( String itsCalled ) {
          this.name = itsCalled;
       }

       @Override
       public void toString() {
          System.out.println( "Flying Donkey:  + name );
       }

       public static void main( String[] args ) {
          System.out.println( "Kiss my grits!" );
          System.exit( 0 );
       }
    }
            

Files, Organization, and Input/Output

Java has some really nice things that can help organize your projects. Because it is a very statically typed language, you do have to make sure that all your types match. That includes types you define yourself in your code. For example, if I want to use the FlyingDonkey class, I will ALWAYS have to instantiate it with the line FlyingDonkey fd = new FlyingDonkey( "Hermione" );, and then forever after the token fd will refer to that specific instance of that single instantiation of the class FlyingDonkey. If at some point I want a different instance of a FlyingDonkey for that token, I must make a NEW instance and ASSIGN that instance to the token. If I want TWO FlyingDonkeys, I have to have TWO instantiations with two separate tokens.

So, part of this is what you saw last week. You make a class for EVERYTHING. Even just the simple Hello world program requires a class file. This fact means you can end up with LOTS of files for the classes in a non-trivial program. However, fear not, for the Java Gods have provided you with a method of organizing things, which we'll see shortly.

In the meantime, though, let's talk about something that we may not have hit on just yet in our learning process, which goes along with Input and Output [or I/O as it's called], and that is the idea of files.

Files can be used to store data. Duh. But that simple fact means that we can store data in a way that is persistent so we can access it again and again. We can also access it in a way that lets it be modified and re-saved for later. We can even use it as input to our programs. Such operations make our programs REALLY useful in all sorts of applications. So, having the availability of file I/O is critical to the success of nearly all applications. Java has a specific package, called java.io which facilitates file operations. There is a class in that package called File which provides what is needed to perform [or start] file I/O.

Java files [in fact nearly all Java I/O] is built on the idea of streams. To get input from something, you need an InputStream, and to output something you need an OutputStream. These are both objects, of course. We've seen an example of an InputStream already, in last week's class exercise. However, for file I/O in Java, the compiler makes you perform some precautionary programming as well, in the form of try-catch-finally blocks.

To use the File class, you must do a lot of coding; however, this coding is worth it, because by HAVING to do the complicated stuff, you must THINK ABOUT what you are doing, which naturally helps you produce better-quality code. Here's an example [which I'll dissect in class]:

   import java.io.FileReader;
   import java.io.FileWriter;
   import java.io.IOException;

   public class CopyFile {
      public static void main(String args[]) throws IOException {
         FileReader in = null;
         FileWriter out = null;

         try {
            in  = new FileReader("input.txt");
            out = new FileWriter("output.txt");

            int c;
            while ((c = in.read()) != -1) {
               out.write(c);
            }
         } catch( IOException ioe ) {
            System.out.println( "\n  Sorry, an I/O error occurred." );
         } finally {
            if (in != null) {
               in.close();
            }
            if (out != null) {
               out.close();
            }
         }
      }
   }

            

Package For Dr. Hackenbush

OK, now we've seen how to do file I/O at a high level. This is the basics of just about any kind of input/output that we'll want to do. Note that JavaScript DOES NOT have anything like this built in, by design. Early on, Java had a thing called Applets, which was a class that allowed web pages to use Java to do things. This was a HUGE security risk [because it let web pages write data to your local hard drive!!], so it was removed, and now most [if not all] modern browsers won't support Applets at all [without overriding stuff and making the conscious decision to take your life in your hands].

Anyhow, the point is, that you might end up with LOTS of files in your Java application program, so you need some way to manage those files. That's what packages and namespaces are all about.

Java provides the idea of packages, which really just means you put all the related files and the modules and so on into a directory together, and then use the import statement to tell the compiler where to find the classes. This is exactly what the Java import statement does. When you see import java.io.FileWriter; at the top of your source code file, that means the compiler needs to go find the code in that package. The java.io part is the package, and the FileWriter is the specific class in that package that you want the compiler to use [or at least to know about]. You could, if you wanted to type a lot more stuff, write the whole thing out every time you are using it. Try this:

   public class CopyFile {
      public static void main(String args[]) throws java.io.IOException {
         java.io.FileReader in = null;
         java.io.FileWriter out = null;

         try {
            in  = new java.io.FileReader("input.txt");
            out = new java.io.FileWriter("output.txt");

            int c;
            while ((c = in.read()) != -1) {
               out.write(c);
            }
         } catch( java.io.IOException ioe ) {
            System.out.println( "\n  Sorry, an I/O error occurred." );
         } finally {
            if (in != null) {
               in.close();
            }
            if (out != null) {
               out.close();
            }
         }
      }
   }
            

The idea here is two-fold. First, the import statement allows you to tell the compiler that you are going to use a specific package, and in fact specific classes from that specific package. Second, it tells the compiler that within the module in which the import is used, it needs to assume [or perhaps infer] that the class is part of that package. The second part of this provides the idea of a namespace.

To make a package, all you need to do is put all the files you want to be in that package into a single directory [often a sub-directory of the application program source directory], and make sure that all the source files in that directory have the line package <packageName>; in them, where <packageName> is the name of the directory where the files are located. By convention, package declarations are the first statement in a source file, following any module documetation statements [comments]. They are also, by convention, always lower-case.

It is, of course, possible to have packages anywhere you want. There is a convention for that, too, which says to use the dot notation and list the directory hierarchy in reverse order. This is why in some of the StackOverflow examples you'll see things like com.blahblah.woofwoof in package identifiers.

Class Designing

Every Java class should have the following key components:

  1. Some sort of file header that describes what is in the file or module. Check out the coding standards page for examples.
  2. A package statement, if applicable
  3. A [series of] import statement[s]. More on this in a minute.
  4. The class declaration statement like public class WhateverYouCallIt
  5. The class fields [also known as data members; values that every object that is instantiated from this class will have, but that may have different values from object to object of these instantiations. These comprise the state of each object. These fields can have one of three accessibility options – public, protected, or private.
  6. The class methods [another word for functions] which provide the behaviors that objects of this class can have. The methods provide a way of operating on the data in the fields, which changes the object's state.
  7. A constructor, which is a special method that is used to make instances of the class, or another way to say it is to make objects from that class. You can have multiple constructors, with or without parameters being passed. The constructor is the usual place to find all the initialization code that sets the initial state of any object that is created [instantiated] from that class. Note that constructors are usually found directly under the fields.
  8. There may or may not be a special method called the main() method. This item has several properties which we'll see in a minute also.

We've already seen some examples of classes that follow this model.

[[Reference to Nutshell book goes here]]
[[live coding example goes here]]

Java Interfaces

One of the things that is nice about OOP is the ability to extend a class. What this means is, being able to add specificity to a general model to make it more closely match the details of what it represents.

...wait..... WHAT?!?....

Let's take one classic case. You have a shape class that has a center and a color, as well as a way to draw itself. What happens if you have a circle shape and a square shape? They are both shapes, but they have very different properties. However, in OOP, that's not a problem, since you can extend the shape class. You can create a circle object that has all the attributes of the shape class [through inheritance] and then ADD extra stuff. The syntax to do that looks like public class Circle extends Shape.

But what happens if you want a class to inherit from more than one other class [superclass]? This is a thing called polymorphism. Java doesn't support this concept directly, but it DOES allow you to provide your own implementations of things by using its interface mechanism. In this way you can have a class that is both a sub-class [inheritor] of another class, and is able to inherit [implement] the behaviors of other classes as well. The syntax to do this is another add-on to class definitions: public class Circle extends Shape implements Blah.

The key to interfaces is that you have to provide the definition [the guts for certain [sometimes all] of the methods in the interface IN THE IMPLEMENTING CLASS. In other words, the interface is a sort of contract between your class implementation and the operations that the interface expects to be implemented. The details of the implementation are left up to you, but the method signatures that are defined by the interface must be followed.

[[live coding example goes here]]

Best Practices

There are several things that are considered best practices when writing Java classes. We have seen most of them sprinkled through this discussion, but here they are all in a list for your easy reference.

[[example goes here; use the Ball.java class as an example]]

OK, now it's time for some practice!! YOUR TURN!!!

In-class Assignment #2

In this week's class assignment we will make a small file copier. The intent of the exercise is for you to get experience with packages, and with having different classes perform different operations as part of the program's functionality.

The file copier will be command line or terminal window driven. For help with file operations, you can do a search using writing a file in java and reading a file in java. Note that the Stack Overflow entries may NOT be as useful as you may think! You can use the CopyFile.java code from the example code above as a starting place. The specifications are as follows:

  1. On a piece of paper, using english words, write a line-by-line definition of what your program should do, as follows. The program should open two files, one for reading and one for writing. The program should then read from the first file, an entire line at a time, and write that line out to the second file. When the first file runs out of lines, close both files and exit the program.
  2. You can write the definition in any way you want, but it is recommended that you use some sort of pseudocode. Check out that example, or do an Internet search to see what that means if you don't know.
  3. Once you have the pseudocode written down, walk your way through it manually to see if it will work the way you expect. This is called a desk check.
  4. Now, make a java source file that will implement your program from the pseudocode. Name your program MyFileCopier.java and include two other classes, with the names of SourceFile.java and TargetFile.java
  5. The MyFileCopier.java file will be the main program and will instantiate the other two as needed, based on the following specifications.
  6. Put the MyFileCopier.java file in the classwork02 directory on your hard drive.
  7. Put the SourceFile.java and TargetFile.java into a subdirectory called copiersupport under the classwork02 directory. Be sure to put the package statement at the top of both of the files.
  8. Be sure to put an appropriate import statement in your MyFileCopier.java file.
  9. Running the program should initially prompt the user for a file name, then should read the user's input and treat that as the file to be copied [the source file].
  10. The main program should then instantiate the SourceFile class, passing the source file name to the constructor; the Source file should then read in the entire source code file, placing the contents in a String which will be returned to the main program.
  11. Once the file has been read, the main program should then instantiate the TargetFile passing the file name to the constructor ALONG WITH the String buffer with the file contents.
  12. The TargetFile instance should then open a new file with a file name which is the same as the name passed in, with the word copy appended to the name. In other words, if the file name is input.txt the target file is named input.txt.copy.
  13. Now the TargetFile must write the contents of the String buffer to the new file.
  14. The main should then close BOTH files.
  15. Test your program by creating a new file called inputfile.txt. Edit the file and put some text into it, save it, then list the file contents using either the more or the less command in the terminal window.
  16. Then test your program again by copying the inputfile.txt file and producing the output file named inputfile.txt.copy. List the file contents of the target file to see that it is a duplicate of the source file.
  17. Upload and commit your completed MyFileCopier.java, SourceFile.java, and TargetFile.java source code files to your GitHub repo for classwork02
  18. As always, pat yourself on the back for a job well done!

Here is some code to get you started:

MyFileCopier.java
   /**
    * Filename: MyFileCopier.java
    * Purpose:  package demonstrator
    * Description: uses two package classes to edit files
    */

   import SOMETHING_HERE
   import SOMETHING_HERE
   import SOMETHING_HERE

   public class MyFileCopier {

      private static SOME-TYPE SOME-INPUT-VARIABLE-NAME;
      private static SOME-TYPE SOME-OUTPUT-VARIABLE-NAME;

     // This is where the constructor goes
     //  you will need to ask the user for the file name to copy
     //  that should go into a variable declared above
     //  you should then use that variable to create the output variable value
     //     as described in the specification above
      public MyFileCopier() {

        // TODO:  You must fill in this part of the constructor

         System.out.println( "\n   Copying " + SOME-INPUT-VARIABLE-NAME +
                                      " to " + SOME-OUTPUT-VARIABLE-NAME );
      }

     // This is the main method for the entire 'MyFileCopier' program
      public static void main( String[] args ) {

         MyFileCopier mfc = new MyFileCopier();                // call the constructor
         SourceFile sf = new SourceFile( sourceFileName );     // open the source file
         String fileContents = sf.getBuffer();                 // read in the contents
         System.out.println( "contents: " + fileContents );    // display them

        // call the target file constructor passing the name and the contents
        //  of the source file you just read AS ARGUMENTS
         TargetFile tf = new TargetFile( targetFileName, fileContents );
         System.exit( 0 );

      }
   }
            

Here is the entire code for the source file object to help get things rolling:

SourceFile.java
   /**
    * File name: SourceFile.java
    * Purpose  : read in the input file
    */

   package copiersupport;           // note that this is the name of the directory!

   import java.io.BufferedReader;
   import java.io.FileNotFoundException;
   import java.io.FileReader;
   import java.io.IOException;
   import java.util.Scanner;


   public class SourceFile {

      private String fileInputBuffer = "";

      public SourceFile( String fileName ) {

         BufferedReader br = null;
         try {
            br = new BufferedReader( new FileReader( fileName ) );
            StringBuilder sb = new StringBuilder();
            String line = br.readLine();

            while( line != null ) {
               sb.append( line );
               sb.append( System.lineSeparator() );
               line = br.readLine();
            }
            fileInputBuffer = sb.toString();
            br.close();
         }
         catch( IOException ioe ) {
            System.out.println( "Error reading input file." );
         }
      }

      public String getBuffer() {
         return fileInputBuffer;
      }
   }
            

And now here is skeleton code for the target file which you will need to fill in:

TargetFile.java
   /**
    * File name: TargetFile.java
    * Purpose  : write out a copy of the input file
    */

   package WHAT_GOES_HERE?;
   import SOMETHING_HERE;
   import SOMETHING_HERE;
   import SOMETHING_HERE;


   public class TargetFile {

      public TargetFile( // YOU NEED TWO VARIABLES HERE; WHAT ARE THEY? ) {
         BufferedWriter bw = null;
         try {
            bw = TODO_LOOK_UP_HOW_TO_CONSTRUCT_THIS;
            bw.write( fileContent );
            bw.close();
         }
         catch( IOException ioe ) {
            System.out.println( "Error writing target file." );
         }
      }
   }
            

When you have completed this exercise and it is all working properly, make sure to commit the code to your gitHub repo. Put it into the classwork02 folder.

Homework Assignment #2

I know this isn't due for a while, but I wanted to give you a heads-up on the homework assignments that you will be doing this semester. They are all available from the syllabus page, but just to make sure …

Week Two Wrap-up

That's probably enough for the this week. Be sure to check out the links to the related materials that are listed on the class links page.