Learn Object-Oriented Java the Hard Way

Exercise 1: Working With Objects

There’s no getting away from it, Java is an object-oriented language. In the original “Learn Java the Hard Way”, I tried to avoid the object-oriented parts of Java as much as possible, but some of them still snuck in!

In this chapter we will look at some common patterns Java uses when creating and working with objects, and I’ll also have a brief reminder of how to compile and execute Java programs from a command-prompt or terminal window.

Type in the following code into a single file called WorkingWithObjects.java and put it into a folder you can get to from the terminal window.

If some of this is unfamiliar, don’t worry about it. We’re just going to be looking at patterns, and the details aren’t that important in this assignment. In particular, you might not have ever used ArrayList or Random, and that’s perfectly fine.

If this code is extremely overwhelming, then you might have a problem. Maybe you don’t know what an if statement is, or System.out.println, or you’ve never used a for loop. In that case, this book is probably going to be too difficult for you. You should go back and work through an easier book first and then come back here once you’re quite comfortable with the basics of Java.

Anyway, type up the code below and then I’ll remind you how to compile it from the terminal. Remember that you shouldn’t be using any IDE for these exercises. Also remember not to type in the line numbers in front of each line; those are just there to make it easier to talk about the code later.

 1 import java.io.File;
 2 import java.util.ArrayList;
 3 import java.util.Random;
 4 import java.util.Scanner;
 6 public class WorkingWithObjects {
 7     public static void main( String[] args ) throws Exception {
 8         File f = new File("datafiles/phonetic-alphabet.txt");
10         if ( f.exists() == false ) {
11             System.out.println( f.getName() + " not found in this folder. :(");
12             System.exit(1);
13         }
15         ArrayList<String> words = new ArrayList<String>();
16         Scanner alpha = new Scanner(f);
18         System.out.print("Reading words from \"" + f.getPath() + "\"... ");
19         while ( alpha.hasNext() ) {
20             String w = alpha.next();
21             words.add(w);
22         }
23         alpha.close();
24         System.out.print("done.\n\t");
26         Random rng = new Random();
27         rng.setSeed(12345);
28         // rng.setSeed(23213);
30         for ( int n=0; n<3; n++ ) {
31             int i = rng.nextInt( words.size() );
32             String s = words.get(i);
33             System.out.print( s.toLowerCase() + " " );
34         }
35         System.out.println();
36     }
37 }

Once you’ve got the code typed in I’m going to assume that you saved the file WorkingWithObjects.java into a folder called javahard2. If you saved it into a different folder, substitute the name below.

Open up a terminal window and change into the javahard2 folder:


(If you’re stuck on a much older version of Windows that doesn’t have Powershell, then you will have to type dir. Everybody else gets to type ls, though.)

Hopefully you’ll see an output listing that includes:

That means you’re in the right place. Then you’ll compile the file using the Java compiler, which is called javac:


If this command gives an error about javac itself, then you skipped Exercise 0! Go back and make sure the JDK is installed and in the PATH, then come back!

Assuming you have good attention to detail and did everything that I told you, this command will take a second to run, and then the terminal will just display the prompt again without showing anything else.

However, if you made a mistake, you will see some error. If you have any error messages, fix them, then save your code, go back to the terminal and compile again.

Eventually you should get it right and it will compile with no errors and no message of any kind. Do a directory listing and you should see the bytecode file has appeared in the folder next to your code:


Now that we have successfully created a bytecode file we can run it (or “execute” it) by running it through the Java Virtual Machine (JVM) program called java:


What You Should See

Okay, now that that is working, let’s talk about some of the patterns we see in this exercise.

Line 1 imports a “library”. java.io.File contains the definition for a object/class called File. Once we have imported it, we can create File objects in our code and call methods defined inside those objects.

The next three lines import three more libraries, each defining an object. Some programming languages call these imported things “modules” instead of libraries. Same thing.

On line 8 we instantiate a File object and name it f. The File object is passed a String parameter containing the name of a file to connect itself to.

On line 9, we now have a File object named f that is somehow connected to the text file on our computers.

On line 15 we created a second object. This is an ArrayList of Strings named words, and instantiating it didn’t use any parameters.

On line 16, we create a third object. This one is a Scanner object, and it uses the File object from before as its parameter.

Finally, on line 26 we instantiate our fourth object: a Random object. Notice the pattern. If you want to instantiate an object called “Bob”, you’d write code like this:

Bob b = new Bob();

Or maybe:

String s = "Robert";
Bob b = new Bob(s);

That’s pretty much how Java creates objects. The keyword new is always involved, and the name of the class (twice) and some parens.

Now let’s look at method calls. A method is a chunk of code inside an object that accomplishes a single purpose, and “calling” a method means asking the object to execute the code in that method for you.

On line 10, we call a “method” named exists() that is contained inside the File object f. This method will return a Boolean value (either true or false) depending on whether or not that file exists. The code that figures out how to do that is contained inside the library java.io.File that we imported. Make sense?

Line 11 features another method in the File class: getName(). It returns a String containing the name of the file associated with the object. If you skip down to line 18 you can also see a method named getPath() being called.

Line 19 calls the hasNext() method, which is in the Scanner class (our Scanner object is named alpha. It returns true if there’s text in the file we haven’t read yet.

The next() method reads a single String from the file and then on line 21 we call the add() method of ArrayLists to add that String to the list.

On line 23 we call the close() method, which closes the Scanner object so that we can’t read from its file anymore.

Line 27 calls the setSeed() method of the Random class, and line 31 calls the nextInt() method of the same class. Line 31 also calls the size() method of ArrayLists, and line 32 calls get() to retrieve a single String out of the list.

Finally line 33 calls a method named toLowerCase(), which is part of the String class. Could you have figured that out if I hadn’t told you? I hope so, because “toLowerCase()” looks like a method call, and the variable s is a String.

Okay, so that’s enough for this exercise. The specific details of how this program works aren’t important, but at this point you should have a good sense of how you do the following in Java:

  1. Import libraries containing classes or objects
  2. Instantiate (or “create”) an object
  3. Call methods on that object

Enough until next time.

“Learn Object-Oriented Java the Hard Way” is ©2015–2016 Graham Mitchell