Chapter:Objects in Java

From Juneday education
Jump to: navigation, search

This page is obsoleted (not maintained) and replaced by:

Object, objects, objects in java, creating objects, using objects, arraylist, api, java's api, javadoc, java api documentation, introduction to objects

Contents

Objects in Java

Meta information about this chapter

Expand using link to the right to see the full content.

Introduction

Creating and using objects are done all the time in Java. This chapter shows the basic cases of how to do this. We start by creating some objects from some of the common classes in the Java API (the Java class library that comes with the JDK).

Purpose

Getting the student familiar with creating objects and invoking (object/instance) methods. Getting the students' hands dirty by typing in some code creating objects from the API classes, and later on invoking methods on the objects.

Goal

The student shall be able to:

  • create an object with no arguments (using new and a call of a constructor)
  • create an object with arguments (using new and a call of a constuctor)
  • get a reference to an object using other means (like calling a method that creates an object and returns the reference to it)
  • invoke a method returning void
  • invoke a method and store the returned data
  • invoke a method with arguments
  • understand the concept of a reference, and that many instances of the same class can exist
  • describe what the Java API is
  • describe what the Java API documentation is and the basics on how to read it

Concepts

Instructions to the teacher

Common problems

Students must learn the concept of name spaces (even if we don't use that term) as in the fully qualified names of classes. A source of confusion could be the fact that classes in the java.lang package don't have to be qualified or imported.

Another source of confusion for students is the different role they can take when writing code. Sometimes a programmer uses predefined classes (classes from the standard Java API or classes from colleagues or third party vendors). Other times, the task of the Java programmer is to also identify classes during the analysis and design phases and writing code for defining such classes. We have seen that these two different tasks can be confusing to the novice student. Our approach in this course is to have the students first using classes someone else have written (perhaps the authors, or classes included in the standard Java API). Only after having created objects and having used them (by invoking methods offered by the objects) we turn to the practice of writing our own classes for custom objects.

Make sure that you don't make the mistake of calling reference variables "objects". It is easy to slip and say stuff like "Here we pass the object name to the println method" (where "name" is a reference to a String, for instance). It is better, albeit cumbersome, to say: "Here we pass the reference variable name to the println method". We have seen many students (new to programming) struggle with understanding references to objects as opposed to the primitive type variables. We should help them by thinking carefully about what words we choose when explaining code to them. Strings are particularly tricky in this regard since it's easy to think "I'm assigning the String 'abc' to the variable s" when we actually are assigning a reference to some String object to the variable s.

We start by creating and using objects of the often used String class. This opens for a minefield of pitfalls, since String objects are a little different from some of the typical objects created from classes written by the students during an introductory course. Some of the things to consider when using and introducing the String class, include:

  • Strings can be created using the double quote construct (rather than being confined to using only calls to constructors and the new operator)
  • Strings created using the double quote construct are put in the String constants pool, which means such Strings are re-used and will have the same reference "address"
  • Strings created using the new operator will not be put in the constants pool and will be separate objects which are not re-used
  • Strings are immutable, which is a good practice, but may cause confusion such as when calling an instance method such as toLowerCase(), you get a reference to a completely new String object, when the intuition of the students might tell them that the actual instance for which the method is called will change its state...
  • String is a class in the java.lang package (as mentioned above) which makes uses of unqualified naming of the class legal and normal - as soon as they learn to use classes from other packages, qualification or import statements are required
  • Using double quotes to create a new String makes the String type look like a primitive type - make sure you don't mislead the students into thinking it is! String is a reference type (and a class) and nothing else

Another thing to think about is the nature of the simple programs students typically write and read early on in an introductory course. It is very common to create a few objects by passing hard coded values to their constructors and then writing the objects state to the standard out. This is not very typical activities in real programs for many reasons. First, real programs tend to avoid having hard coded values (and rather gather data from external sources during runtime). Second, real programs don't normally create objects solely for the purpose of immediately printing them. Third, real programs usually don't do all their work in the main method alone. The problem we have to handle is, that students don't have enough knowledge early on in the course to write bigger and more typical programs. So we have to compromise with this principle in order to start with very simple programs. It is up to us teachers, however, to handle how we present the small typical course book example programs, and to make them at least a little interesting. As soon as we introduce user supplied data for the state of objects, the programs become much more interesting (and more similar to "real programs"). One of the fascinating things about programs, is that we can write one program to solve a general task, and it will solve it the same way regardless of what data we feed it.

Think about a calculator, for instance. Isn't it much more fascinating that a calculator can multiply two arbitrary numbers that we supply? Compare that to the typical "learning operators exercise" where the student creates two variables a and b, and assigns 10 to a, and 20 to b. Then the program prints something like "10 * 20 = 200". At least some students will silently think "But I knew that already".

Chapter videos

All videos in this chapter:

See below for individual links to the videos. We have divided the chapter into two basic sections; Creating objects and Using objects.

Objects - a short introductory video

Description

The video lecture for this section is just a short introduction to objects.

Videos

  1. Objects (eng) (sv) (download presentation)

Classes - a short introductory video

Description

This video lecture is just a short introduction to classes, so that students at least have some information on the relation between classes and objects. Classes (writing our own classes) is a topic for a later chapter in which we will go into more detail about the writing of classes, their different contents and syntax.

Videos

  1. Classes - an introduction (eng) (sv) (download presentation)

Creating objects

Description

This section will introduce how to create objects using a call to the constructor via the new operator keyword. The exercises will focus on creating objects from classes included in the standard Java API, and contain additional explanations.

Videos

  1. Creating objects I (eng) (sv) (download presentation)
  2. Creating objects II (eng) (sv) (download presentation)

Exercises

Creating String objects

Exercises for creating objects. Let's start by creating some objects which are described in classes that come with the Java installation. Such classes are also said to be part of "the Java API" (API: application programming interface), or "the Java Class Library". What's important to understand, is that when you install Java, you get a huge library of classes which you can use. This is why we have been able to use, for instance, the class String in some of the example Java programs we have looked at in previous chapters.

Classes are organized in packages. Packages are just directories in a hierarchical structure. Orginizing classes in directories makes for a logical grouping of related classes. Packages are normally many directories deep. Most of the standard Java classes from the API, exist in packages starting with java., such as java.lang.String. The actual class is called String, but it is located in the java.lang package. The full name of the class is hence java.lang.String. That the actual class is called String is obvious for two reasons; 1. The name String comes last in the full name. 2. The only thing that contains (and in particular starts with) a capital letter is the class name String.

Strings are very commonplace in Java programs which is why the String class is located in the java.lang package. Classes in that package are always available to the programmer. By "available", we mean that you can always use the class names directly, without including the package name. Classes in other packages cannot be used without one of the following two techniques:

  1. The programmer (you) always writes out the full name, including the package
  2. The programmer puts an "import statement" indicating what classes (and what packages) will be used in the code

Let's start with a simple use of the String class. Create a directory called objects_in_java and navigate to that directory. This is the directory you will use for the exercises in this chapter.

Next, inside the newly created directory, create the following directories:

org/progund/strings

They can be created all at once, using the following command in your shell:

$ mkdir -p org/progund/strings

Or you may create them incrementally, using three consecutive mkdir commands:

$ mkdir org
$ mkdir org/progund
$ mkdir org/progund/strings

Use the technique you feel most comfortable with. (The -p flag for the mkdir command, tells mkdir to create a whole hierarchy at once).

Now, start your editor so that it creates a new text file called UsingStrings.java in the org/progund/strings directory, and enter the following Java code:

package org.progund.strings;

public class UsingStrings{
  public static void main(String[] args){
    String aName = new String("Adam");
    System.out.println("The String aName has the value: " + aName);
  }
}

Compile and run this small program. You can see in the solutions section an explanation of what the different parts of your program represented. To compile issue the following command (you should still be in the same directory as before!):

$ javac org/progund/strings/UsingStrings.java

You are telling the compiler javac to compile the Java source code file org/progund/strings/UsingStrings.java. It will create the byte code file org/progund/strings/UsingStrings.class (next to your Java program).

To run the program, issue the following command (you should still be in the same directory as before!):

$ java org.progund.strings.UsingStrings

What was printed to the screen? Now, add a few lines of code to your program, which will create and print a second String. This time we will show you a common way to create String objects, without using the new operator to invoke the constructor in the String class. You should note that this alternative technique, is only available for creating objects of type String! It was added to the Java programming language to make things more convenient for programmers, since strings are so commonplace in programs. This is what the program should look like with the two extra lines of code using the second technique for creating a String object:

package org.progund.strings;

public class UsingStrings{
  public static void main(String[] args){
    String aName = new String("Adam");
    System.out.println("The String aName has the value: " + aName);
    String aFlower = "Tulip";
    System.out.println("The String aFlower has the value: " + aFlower);
  }
}

If you run your program again, what would happen? Feel free to try, but you probably know already that you must compile the program again, in order for the changes to the source code to be incorporated in the byte code file that the java command runs. So compile again, and then run the program again. Guess what will be printed this time! Compile/run commands:

$ javac org/progund/strings/UsingStrings.java
$ java org.progund.strings.UsingStrings

What was printed to the screen now? Did you guess correctly? See the solutions for an explanation of every line of code again, if you do not understand what is going on.

Sending information to the main method

So far, we have seen programs in which we have programatically (using code we write ourselves) given objects values. But it is a little strange to write a program which gives for instance a String a value (the same value every time the program runs) and then prints it to the terminal (using System.out.println). It is strange, because you might think "Couldn't I just as well had written the string in the terminal myself?". Normally in a program, variables get their values from external sources like the user inputting values, the system environment variables, reading from a source on the internet, or, from a file.

In the next exercise, we want you to write a new program which gets different values for some variables each time the program is running. The values for the program to use are provided on the command line when the java command is called.

Before we start, we'd like to refresh some old things we talked about early on in the book. You might remember the concept of giving arguments to programs? You have been doing it many times already, actually. When you compile a Java source code file, you use the command javac and you give the command an argument - the file you want to compile. When you later run your Java program, you invoke the JVM via the command java and you give the command an argument - the name of the class (the class that has the main method). But can you pass arguments also to the main method? Of course you can! This is how you do that:

$ java some.packages.ClassWithMain argument1 argument2 ...

The ... at the end symbolizes that you could go on and add arguments on the command line. What would happen is that all the arguments, in the order you wrote them, will be passed on to the main method (the JVM is kind enough to help us with that!). But where do the arguments end up, inside the main?

Remember the signature (more accurately the definition) of the main? public static void main(String[] args)? The arguments (if any are given) end up in the args variable. The args variable is a parameter to the main method. A parameter (we'll talk more about parameters soon) is a way for a method like main to accept arguments. When we give arguments to println() for instance, they end up in some parameter of the code defining the println method (in the class PrintStream, but that is not important to know right now).

So what is special about the args parameter variable? You have probably noticed the square brackets between String and args. Square brackets (they always come in pairs when used like this) are separators that indicate a list of values. Such lists are called arrays. We'll talk more about arrays at a later point, but for now you need to know that String[] means "an array of String references".

An array has a length (the number of elements in the list) and each element has an index (starting at 0 for the first element, and then it increments by one up until the last element which has the number equal to "length minus one").

The args parameter is a variable referencing an array of String references. If the JVM passes on any arguments from the command line to the main method, it inserts them into this array with the first argument at index 0, the next argument at index 1 and so on.

There a few more things we need to know about arrays right now, and that is how to dereference a value at a certain index. If we have args, and args refers to an array of Strings (actually String references), and we'd like to do something with the String at index 0 (the first argument), we would use the square separators again, but this time to indicate an index:

    String firstArgument = args[0];

So, args[0] here means "the value in the args array at index 0". But, what happens if there were no arguments? Then the array would have no elements (a length of 0). Having no elements means that args[0] would be illegal and cause an exception (an error-like situation in the execution) and the program would actually crash. So before we dereference the String at index 0, we'd better make sure that the length is not 0! We'll use a simple if-statement for that, using a comparison of the length against 0.

But how do we ask an array object for its length? We use a dot separator to access the array's length member: args.length. The if-statement for the conditional access of element 0 then becomes:

    if( args.length!=0 ){
      String firstArgument = args[0];
    }

If you need to review the material on blocks and if-statements, now is a good time to do so. We don't want firstArgument to be a local variable only visible inside the if-statement block (if we discover that we need it later in the main method!), so we declare it outside the if-statement and we initialize it to an empty String:

    String firstArgument = "";
    if( args.length!=0 ){
      firstArgument = args[0];
    }

Now it is time for you write some code! The complete program for you to write is the following:

package	org.progund.strings;

public class PassingValues{
  public static	void main(String[] args){
    String firstArgument = "";
    System.out.println("You gave " + args.length + " arguments.");
    if( args.length!=0 ){
      firstArgument = args[0];
      System.out.println("The first argument was: " + firstArgument);
    }
  }
}

The class PassingValues belongs to the org.progund.strings package. Do you remember what the file must be named, and where the file must be saved?

The file must be named PassingValues.java and must be saved in the directory org/progund/strings/. The relative path from the current directory (you haven't left the objects_in_java directory, have you!?) to the file must be: org/progund/strings/PassingValues.java.

To compile and run you can use either:

$ javac org/progund/strings/PassingValues.java
$ java org.progund.strings.PassingValues my-first-argument

or:

$ javac org/progund/strings/PassingValues.java && java org.progund.strings.PassingValues my-first-argument

The argument to the program in the example above was my-first-argument. What did the program print?

Try running the program a few times but giving different arguments. Try without any arguments and try with many arguments. Try giving an argument surrounded by double-quotes and a whole sentence like "This is my first argument". What can we learn about quotes and arguments containing spaces?

Arguments challenge exercise

A challenge for the ambitious student: Change the program so that it writes "You gave one argument" (without the "s") if there was only one argument, and to keep the plural "s" if there were more than one arguments.

Se the solutions below for an explanation of the program (in less detail this time, since you have already learned the basics!).

Looping through the arguments

A sad truth about the previous program, is that we only write the first argument if there are one or more arguments. Since we don't know how many arguments the user passed to the main method, we don't know when to stop so we only wrote the first. We could have gone on and written something like:

    if(args.length > 1 ){
      System.out.println("second argument was: " + args[1]);
    }
    if(args.length > 2 ){
      System.out.println("third argument was: " + args[2]);
    }
    if(args.length > 3 ){
      System.out.println("fourth argument was: " + args[3]);
    }
    // etc - but when to stop???

But that would have been even sadder! What if the user provided 500 arguments (just to prove us stupid)? There must be a way to handle every case (every possible number of arguments) generically! And there is! You might have guessed already, but since we know that we can ask args about the length (the number of arguments), we could use a loop for this!

To loop through every item of an array is so common that there is an idiom for this (as we'll see, there are actually two idioms). We know that we should start at 0, and access every index until we reach the last one (index (length - 1)). So we could use a for loop for this (a while loop would work equally well, but the idiom is to use a for loop):

  for (int i = 0; i < args.length; i++){
    // do something with each element, like print it:
    System.out.println("Argument number " + i + " was: " + args[i]);
  }

This is a standard way of iterating over the elements of an array. There is an alternative way, called the "for-each loop". We haven't seen it yet because we didn't know arrays (and other lists) existed until just recently! Here is the same loop as above using the for-each loop:

  int i = 0;
  for (String arg : args){
    // do something with each element, like print it:
    System.out.println("Argument number " + i + " was: " + arg);
    i++;
  }

The drawback of using the for-each loop here is that we have to create the index variable i outside (before) the loop, and we have to remember to increment it inside the loop after we've used it. If we need to use the index value, the for-each loop makes less sense, since we'd have to manage the index counter variable ourselves. But if we don't care about the index number, and just want to print every element of an array, the for-each loop makes things a lot smoother. Compare the following two snippets:

  for (int i = 0; i < args.length; i++){
    System.out.println(args[i]);
  }

and, using the for-each:

  for (String arg : args){
    System.out.println(arg);
  }

Your task is to write a program in the class org.progund.strings.WriteAll (in the file org/progund/strings/WriteAll.java ) which writes out every argument (if any) given to the program. You may choose to use the standard for-loop or the for-each loop, whichever feels more natural to you. Try both printing the index number and skipping the number and only write the argument strings.

Food for thought: Do we need an if-statement as well? Or does the for loop cover also the case of no arguments? Think about the condition of the for loop: i < args.length. What does that evaluate to when i is 0 and args.length also is 0?

Solutions

Expand using link to the right to see the full content.

Explanation of the UsingStrings program

 1 package org.progund.strings;
 2 
 3 public class UsingStrings{
 4   public static void main(String[] args){
 5     String aName = new String("Adam");
 6     System.out.println("The String aName has the value: " + aName);
 7     String aFlower = "Tulip";
 8     System.out.println("The String aFlower has the value: " + aFlower);
 9   }
10 }

Download this file here if you want to look at it. Remember that if you want to compile and run it, it must be in the correct directory structure!

Line 1
1 package org.progund.strings;

This is a package statement. Package statements are always the first line of code in a compilation unit (like a Java file with a class declaration). Usually every Java class belongs to a named package like this. Examples without the package statement leave it out to make things shorter - but in the real world, classes belong to packages, and packages always symbolizes the path to the file where the class is saved.

You created the directory structure org/progund/strings and put your Java file in that directory. Now, org/progund/strings/UsingStrings.java is a relative path to the Java file you wrote (relative from the directory where you first created the org... directories -- this is also the directory where you were when you compiled and ran your program). The package statement starts with the keyword package and then lists the directories leading to the class you are defining in the source code file. But instead of the usual / (forward slash) used as directory separators, in the Java programming language, packages us a dot . as a separator. The package statement ends with a semicolon ;. The semicolon is called a "separator" in the Java language. It is used to separate statements from each other.

You can think of the package statement on line 1 as meaning: "The class defined in this file belongs to the package org.progund.strings". This is now part of the full name of the class you are defining on lines to come.

Line 2

Empty line for readability - a Java source code file may have any amount of empty lines - they will be ignored by the compiler.

Line 3
3 public class UsingStrings{

Here begins the definition of a class called UsingStrings. Public classes like this may only be declared on a one-per-file basis (this rule applies to top-level classes - the first class declared in a source code file. Classes may declare classes inside them, but that is not material for this introductory course, and you may ignore that fact for now!).

The keyword public means that this class is available for any other classes that might be part of the same program (but we only have one class in this simple program). The left-curly-brace { at the end of the line is the start of the block of the class declaration.

Line 4
4   public static void main(String[] args){

On this line, the mandatory main method (the starting point for all Java applications) is being declared. This is where the execution will begin. The syntax of the main method is something you will learn by heart after writing many Java programs. We have discussed it in previous chapters if you want to review it. The static keyword will be discussed later in the book, but for now you can think of it as meaning "has nothing to do with objects, only the class". It has nothing to do with objects of the class you were defining, because the Java Virtual Machine (the java command) can run the main method to start the execution, without having to create any objects of your class. Much more on the static keyword later!

Line 5
5     String aName = new String("Adam");

On this line, you are doing a few things at the same time! You are declaring a reference variable that you called aName and the type of objects the variable can refer to is objects of class String.

Line 6
6     System.out.println("The String aName has the value: " + aName);

This is a revisit to the System.out.println() method call. As you probably remember, a call to System.out.println() makes your program to output text to the console (the terminal window where your program was run). The interesting part of this statement, is the use of the + operator! It is not used as an arithmetic operator here. It is used to join to String expressions together. On might say that the + operator is "overloaded" - which is to say that it has more than one use. It can be used as an addition operator (as we've seen in previous chapters) but also (as we see here) as an operator to joint two String expressions together. Joining two Strings is sometimes called "concatenating" two Strings. The result is actually a completely new String object with the value of the two operands joined together.

Note the first expression in the parentheses of the call to println. It is surrounded by double quotes. This is a way to create a new String with the value of the text within the double quotes. Note in particular that the text inside the double quotes end in a space. This is because we want to join it with the value of the String object which anName refers to ("Adam"). We want the resulting text to be exactly:

The String aName has the value: Adam

Since the value of the String object which aName refers to is simply "Adam" (without a preceding space), we make sure that the first String ends in a space, so that the result of joining the expressions looks readable.

It is quite common that when we want to print the value of some variable, we join some explanatory text, ending in a space, with the variable itself. The space at the end of the explanatory text makes sure the resulting text is more readable. Try and remove the space at the end of the first part so that it reads simply The String aName has the value: (without the trailing space), save the source code, recompile and run the program again. The result would look like:

The String aName has the value:Adam

That's much less readable (and less pretty), isn't it?

Line 7
7     String aFlower = "Tulip";

This line declares another String reference variable, this time named aFlower, and assigns it a reference to a newly created String object with the value "Tulip". The perhaps surprising thing about this statement, is that there is no call to the constructor of the String class via the new operator, yet a String object is created. This is an exception to how explicit object creation is done in Java. Strings are so common, that they decided to allow a simplified form of a constructor call, using string literals inside double quotes. Wherever you see a quoted string in Java code, the compiler will translate that to some form of constructor call, so each quoted String will be replaced with a new String object with the quoted value as the string value represented by the object.

Is that all it is to it? Unfortunately not. We will later see that quoted Strings are re-used, while Strings created the normal way, using new String("Some text"), are not re-used. There, we've said it, but you don't have to care about that just yet!

Line 8
8     System.out.println("The String aFlower has the value: " + aFlower);

This line uses the println method of the out object in the class System as usual, to print something to the terminal (the standard output stream, which is normally connected to the terminal where the Java program was run). As before, two Strings are concatenated into a new, longer, String which is printed out. And, as before, the first String in the expression (the argument to println) ends in a blank space so that the next String comes after the blank. The resulting String which is printed is The String aFlower has the value: Tulip. So, once again, we had concatenated some descriptive text and the value of the object represented by a variable (in this case the variable aFlower). And, you probably have seen by now that all statements so far end in the semicolon separator.

Line 9
9   }

This right-curly-brace ends the block of the main method. Execution ends before this line!

Line 10
10 }

This right-curly-brace ends the block of the UsingStrings class.

Not that the program uses indentation (did you use that too?). Indentation was when we aligned all statements inside a block to the same number of spaces. If you look at the code again, you'll see that stuff belonging to the outermost level (like the package statement, the class declaration and end-curly-brace, are aligned to the left margin. But all statements inside the class block (in this case, only the declaration and end-curly-brace of the main method) start at two spaces further to the right. And the statements inside the main method all start at an additional two spaces to the right. This style is only for us humans, so that we easier can see that statements at the same indentation level belong together (they are inside the same block). The compiler doesn't care at all about indentation. But we (the authors) do, and probably will your future colleagues also do, so, you should care too!

Explanation of PassingValues.java

 1 package org.progund.strings;
 2 
 3 public class PassingValues{
 4   public static void main(String[] args){
 5     String firstArgument = "";
 6     System.out.println("You gave " + args.length + " arguments.");
 7     if( args.length!=0 ){
 8       firstArgument = args[0];
 9       System.out.println("The first argument was: " + firstArgument);
10     }
11   }
12 }

Download this file here if you want to look at it. Remember that if you want to compile and run it, it must be in the correct directory structure!

We'll focus on the statements in the main method (see above for the details of the package, class and main declarations).

 4   public static void main(String[] args){
 5     String firstArgument = "";
 6     System.out.println("You gave " + args.length + " arguments.");
 7     if( args.length!=0 ){
 8       firstArgument = args[0];
 9       System.out.println("The first argument was: " + firstArgument);
10     }
11   }

First we declare a String reference variable called firstArgument and initialize it to refer to a String object representing the empty string. An empty string is just two double quotes with nothing between them.

Second, we call System.out.println and we give it an expression using the concatenation of three operands as the argument. When this is run, the Java runtime will evaluate the expression to a new String using the string concatenation operator +. What is interesting about this, is that only the first and last operands actually have the type String! The middle operand, args.length is actually of type int. How is this possible? The rule is that when using +, if one of the arguments is a String, the other argument will be promoted to a String if it isn't already a String! But how does the JVM promote an int to a String? It actually creates an intermediate object of class Integer, using the int as the argument to the constructor. An Integer object is the object equivalent of the primitive type int. Next, it calls a method on the Integer object called toString() which turns the integer value into a string with the textual version of the value.

We haven't talked so much about methods yet, so don't worry if you didn't fully understand that. What is important to understand at this point is that if you use + to concatenate a String and an int, the result will be a string where the last part is the int as you would type it in a string. An int of value 1 will be converted to a String of value "1" (the character "1" as text).

The int in question here is the result of the sub-expression args.length. You can think of an array as an object which has a variable called length. To access a particular array's length variable, you write the reference variable followed by a dot and then the length variable. So the expression args.length could be understood as meaning: "the value of the length variable of the array referred to by args".

The purpose of this statement is to output to the terminal a text describing how many arguments were given to the main method. If no arguments were given the resulting text would be You gave 0 arguments. and if you gave five arguments, the text would be You gave 5 arguments. instead.

Third, we use an if-statement that uses the claim that args.length is not 0. This means that the body (the code in the block) of the if-statement will only be executed if args.lengh was something other than 0, i.e. if there were some arguments given to the main method.

Fourth, we - inside the block of the if-statement - we assign the firstArgument variable a reference to the String at index 0 of the args array (the first argument, since the arguments are put in the array in order starting with index 0).

Fifth, we output text describing the value (the text) of the first argument (now stored in firstArgument).

Note, that since we declared firstArgument outside (before) the if-statement block, we could continue to use it after the if-statement if we wanted to. If we'd declared the variable inside the if-statement, we'd be forbidden to use it outside (after) the if-statement since it would have been a local variable visible only in the block of the if-statement! Revisit the section about blocks and if-statements if you fail to remember or understand this!

Finally, some words on using quotes around arguments. This is useful when you want to give a string as an argument but the string contains spaces. If we'd written my first argument as the arguments to the program, the following would happen:

$ java org.progund.strings.PassingValues my first argument
You gave 3 arguments.
The first argument was: my

That is because each word would be interpreted as a separate argument. In order to send the sentence as one argument, we'd have to use quotes:

$ java org.progund.strings.PassingValues "my first argument"
You gave 1 arguments.
The first argument was: my first argument

Suggested solution - arguments challenge exercise

Suggested solution to the challenge exercise (using "argument" for one argument and "arguments" for more than one):

  public static void main(String[] args){
    String firstArgument = "";
    String argumentString = " argument";
    if( args.length > 1 ){
      argumentString += "s";
    }
    System.out.println("You gave " + args.length + argumentString + ".");
    if( args.length!=0 ){
      firstArgument = args[0];
      System.out.println("The first argument was: " + firstArgument);
    }
  }


Proposed solution to WriteAll

Our proposed solution uses all four combinations of the loops. First the standard for loop, which also writes the index number, next the for-each loop that also writes the index number (but we have to provide an index variable that we increment ourselves), next the standard for loop without writing the index, and finally the for-each loop without any index.

Download this file here if you want to look at it. Remember that if you want to compile and run it, it must be in the correct directory structure!

package org.progund.strings;

public class WriteAll{
  public static void main(String[] args){
    /* Classic for loop with printing of index */
    System.out.println("Using classic for loop");
    for(int i = 0; i<args.length; i++){
      System.out.println("Argument #" + i + ": " + args[i]);
    }

    /* For-each loop with printing of custom index */
    System.out.println("Using for-each loop");
    int index = 0;
    for(String arg : args){
      System.out.println("Argument #" + index + ": " + arg);
      index++;
    }

    /* Classic for loop without printing of the index */
    System.out.println("Using classic for loop without index");
    for(int i = 0; i < args.length; i++){
      System.out.println(args[i]);
    }

    /* For-each loop without printing of index */
    System.out.println("Using for-each loop without index");
    for(String arg : args){
      System.out.println(arg);
    }
  }
}

You might notice that in the for-each loop with a custom index, we named the index variable index. Can you figure out why we couldn't use the name i in this case? Hint: It is declared outside (and before) the last classic for loop and what does that for loop call its loop variable?

To compile and run the program, you can use the following:

$ javac org/progund/strings/WriteAll.java && java org.progund.strings.WriteAll a b c d e
Live coding videos for WriteAll

We have made two videos where we code a solution to this exercise here and we elaborate on the "food for thought" here.

Links

Using objects

Description

Now that we've seen how to create objects, we'll look a little at what we can do with the objects.

The point in this section is to show you how you use objects by sending messages to them. Sending messages is another way of saying "calling an instance method of an object" or "invoking an instance method of an object".

We've learned that our programs deal a lot with objects. We've seen a few ways of creating objects but we haven't really interacted with the objects. The typical way of using objects in a program is to call methods on the objects, which is like asking the objects to perform some task. Sometimes they silently perform some task which affects other objects or things outside the program (perhaps a web page is loaded and displayed to the user, perhaps a file is saved on the hard drive). Other times, they give as feedback by sending information back to the caller of the method. In later sections, we will also see that we can send references to other objects to an object if they need to work together to perform some task (we've actually seen a version of that, such as when we send a reference to a String to the println method of the object referred to by System.out - the System.out object needs a reference to a String object in order to print it to the standard out stream).

We'll see a few new classes from which we create objects and we'll see that we can ask certain classes to give us references to objects. And we'll see the syntax for calling instance methods via object references.

An instance method is a method that is declared to operate on the state of a particular object (remember an object can also be called an instance of a class). Instance methods are declared in the classes describing objects of the same type and they are declared without the static keyword (that we've seen in the main method - the main method is not an instance method, it is said to be a class method or simply "static method").

The point of instance methods is that all objects are modeled by some class where their data (state) is described, their constructors are described and their behavior is described. So objects of the same class are very similar in structure and behavior. But objects are kind of individuals, so their state (internal data) may differ. So when we want a particular object of some class to do something based on its specific state, we use an instance method. We call the instance method typically using a reference variable referring to the object. The method now executes and it has access to the state (stored in instance variables) of this particular object.

If we have a class describing users in a computer system we can create several User objects from some constructor in the User class. Even though they are all instances of the User class, they will probably have different state. The state can be a user name (stored in an instance variable of type "reference to String" for instance), an email address and a password for instance. The behavior can be for instance that users may change their password. If we send the message to change password for one User object, we don't want the password to be changed for every User object in the system. This is why instance methods are really handy. An instance method for changing the password would only operate on one particular object and we call it for that object using a reference to it.

Before we dig into creating our own classes for creating objects, we'll use some more of the Classes that are included in the Java standard library (the Java API). We'll look at Property objects (that hold settings as key-value pairs), and we'll look at a type of List class for creating list objects that can hold for instance a list of String references, but behave more flexible than the array we've seen previously.

Videos

  1. Using objects (eng) (sv) (download presentation)
  2. Invoking methods in objects (eng) (sv) (download presentation)
  3. Getting information from objects (eng) (sv) (download presentation)
  4. Objects using other objects (eng) (sv) (download presentation)

Exercises

Let's look at some more classes from the Java API and what we can do with objects of those classes.

System properties

We'll start with a class called java.util.Properties which is a class describing objects whose purpose is to hold a list of settings in the form key-value. A Properties object can store information in a way that reminds us of a dictionary - if we want to store our favorite color, we can store it as a key-value pair in a Properties object, so that we later can look up "favorite_color" and get the color back. In the same Properties object we can store as many key-value pairs we want, as long as the keys are unique. So in the same Properties object we could also store our favorite programming language using for instance the key "favorite_programming_language". Later in the program, if we have access to the Properties object, we can retrieve both "favorite_color" and "favorite_programming_language".

But before we create our own Properties object, we'll actually ask the System class to give us a prefabricated Properties object with key-value pairs for information about our computer system! The System class offers a way to get such a Properties object via a call to System.getProperties(). Note that this call is not an instance method call! We don't have any instance of the System class (and the designers of the Java API have decided that we don't need to create one either!). We call the getProperties() method directly via the class name System, and store the reference to the Properties object we get back like this:

    Properties systemProps = System.getProperties();

After that we can use the Properties object with the system properties via the reference variable systemProps. However, there is one problem we have to fix first. The Properties class is located in the java.util package. So we have to import the class using an import statement, before we are allowed to use the class Properties.

You may remember that we didn't have to use any import statement when we were only using the String class and System class previously. You may also remember that both String and System were located in the package java.lang. The thing that was special with that package, was that we didn't need to import the path to that directory in order to use the classes in it. That was an exception to the rule that we always need to import classes that are in a different package than the class that needs to use the classes.

So, our program where we investigate the Properties object we get from System.getProperties() needs to have an import statement importing the java.util.Properties class, before the class declaration.

Let's look at the code you should write for the first program which uses the system properties. It will declare a reference variable of type "reference to Properties" and it will be assigned a reference to the Properties object we get from the System class. Then we'll ask the Properties object to list itself to the standard output stream (print itself to the terminal if you'd prefer that description) using the instance method list() and we'll give it the argument of System.out (which is an object that is connected to the stream that can output text to the terminal as we have seen when we've used System.out and the println() method).

The program should not belong to the package we used when we were playing with String objects. It should instead belong to theyorg.progund.props package. But we don't have the corresponding directory yet, so we must create that first. You should still be in the objects_in_java directory, as before. Issue the following command to create the directory:

$ mkdir org/progund/props

Remember, the org/progund directory is there from the previous exercises, so all we needed to do was to add the props directory inside the org/progund directory.

Your directory structure (if you are still in the objects_in_java directory) should now look like this:

.
`-- org
    `-- progund
        |-- props
        `-- strings

The source code file for the program should be named ListSystemProps.java and saved in the org/progund/props directory since the source code belongs to the org.progund.props package and declares a class called ListSystemProps.

This is the program code that you should write (finally!)

package org.progund.props;

import java.util.Properties;

public class ListSystemProps{

  public static void main(String[] args){
    Properties systemProps = System.getProperties();
    systemProps.list(System.out);
  }

}

To compile and run (still from the same directory as before, objects_in_java) issue the following commands

$ javac org/progund/props/ListSystemProps.java && java org.progund.props.ListSystemProps

Note that a lot of system properties are being printed! Let's use the filter command grep to only display the properties that have to do with user settings:

$ javac org/progund/props/ListSystemProps.java && java org.progund.props.ListSystemProps | grep user

Note the | grep user at the end of the command line. The grep filter is included in your environment (GNU/Linux, Mac OS, or, Cygwin) and has nothing to do with Java programming. But we thought it would be interesting for you to see it in action! It is very useful to filter out interesting parts from a large amount of text.

What is the value of your property with the key "user.name"?

What is the value of your property with the key "user.language"?

What is the value of your property with the key "user.home"?

Accessing individual property values

In the next program (in the same package!) we'll see how to get the values of a certain property if we know the key. The class should be called GettingValues and belong to the org.progund.props package. What must we name the file, and where must we save the file?

If you answered "The file must be named GettingValues.java and be saved in the org/progund/props directory", then you are really starting to learn the use of packages! If you answered something else, please review the previous exercises.

Here's the code for the GettingValues class:

package org.progund.props;

import java.util.Properties;

public class GettingValues{
  public static void main(String[] args){
    Properties systemProps = System.getProperties();
    String javaVersion = systemProps.getProperty("java.version");
    String operatingSystem = systemProps.getProperty("os.name");

    System.out.print("I'm running Java " + javaVersion);
    System.out.println(" on a " + operatingSystem + " machine.");
  }
}

You can look at the Solutions section below for some comments of what was going on in the previous two programs.

A custom Properties object

Next, we'll create our own Properties object and populate it with some keys and values. We'll also use the system properties object to get some values and add them to our own Properties object.

The fully qualified name of the next program should be org.progund.props.CustomProperties (so, as usual, we need to save the source file accordingly in org/progund/props/CustomProperties.java

Here's the code for the CustomProperties class:

package org.progund.props;

import java.util.Properties;

public class CustomProperties{
  public static void main(String[] args){
    Properties favorites = new Properties();
    favorites.setProperty("favorite.color", "Pink");
    favorites.setProperty("favorite.programming_language", "Java");

    Properties systemProps = System.getProperties();
    favorites.setProperty("favorite.encoding", systemProps.getProperty("file.encoding"));
    System.out.println("These are a few of my favorite things:");
    favorites.list(System.out);
  }
}

To compile and run this program, use the following:

$ javac org/progund/props/CustomProperties.java && java org.progund.props.CustomProperties

What favorite file encoding was listed? (A file encoding is a way to code text files on the hard drive - the encoding listed comes from the system property file.encoding which is the default encoding for text files on your system)

Please see the solutions section below for comments on how the code works.

Using ArrayList

Let's leave the Properties class for now and instead look at a class for creating objects representing lists. Also in the java.util package is a class called ArrayList. We've seen how to use arrays of String references, when we used the args variable with the arguments to the main method, previously. Arrays are useful, but they are a bit limited from an object oriented perspective. Arrays have no instance methods, and the only things we an do with arrays is to query the length variable for the number of elements in the array, and access the various elements using the index number with the [ ] square brackets separator. But more importantly, what we didn't say before was that arrays are fixed in size. Once an array is created, there is no way to change the size (number of possible elements). This quickly becomes a problem if we dynamically (during the course of the execution of the program) want to add elements, and we reach the maximum number of elements.

The class ArrayList comes to our rescue! An ArrayList object acts pretty much like a normal array, but it is growing dynamically. There is no maximum fixed size, so we can keep adding elements, without worrying that we reach the maximum size (unless the memory of the virtual machine or physical system runs out).

ArrayList objects also have instance methods, as all decent objects have. We can ask the object about its state, and we can ask it to remove all elements, query the object of what index a certain element has and more.

When we create an ArrayList, we need to provide the name of the class of the elements to be stored in the list. This is to help us getting type safety, so that we don't add elements of incompatible types by mistake. The compiler will help us ensure that an ArrayList for a certain class of elements only gets populated with references to objects of the correct type.

This is the syntax for declaring and creating an ArrayList for storing String references:

ArrayList<String> nameList = new ArrayList<String>();

Alternatively, you may use the slightly shorter form:

ArrayList<String> nameList = new ArrayList<>();

The empty "diamond" <> on the right-hand side works, because the compiler can figure out that you mean to create an ArrayList for String references, because you explicitly said so on the left-hand side.

Let's create a program which creates an ArrayList<String> and uses some of the instance methods on the object. We don't want the class for this program to belong to any of the packages we've declared so far, so we need a new directory for the package. Let's call the directory lists and create it like this:

$ mkdir org/progund/lists

So, the package we'll use will be called org.progund.lists

We'll call the program NameList.java

Here's the code for the program:

package org.progund.lists;

import java.util.ArrayList;

public class NameList{
  public static void main(String[] args){
    ArrayList<String> nameList = new ArrayList<String>();
    nameList.add("Adam");
    nameList.add("Ana");
    nameList.add("Bart");
    nameList.add("Lisa");

    System.out.println("We now have " + nameList.size() + " names:");
    System.out.println(nameList);

    if( nameList.contains("Bart") ){
      System.out.println("The index of Bart is " + nameList.indexOf("Bart"));
    }

    nameList.remove("Bart");
    System.out.println("We now have " + nameList.size() + " names");

    if( nameList.contains("Bart") ){
      System.out.println("Bart is still there!");
    }else{
      System.out.println("There is no Bart in the list any more.");
    }

    System.out.println("Let's clear the list!");
    nameList.clear();
    System.out.println("We now have " + nameList.size() + " names");
    if( nameList.isEmpty() ){
      System.out.println("The list is now empty.");
    }
  }
}

Please see the solution section for comments on how the program works. You don't need to understand everything yet, this is just an exercise to demonstrate how you use a reference variable to call instance methods on a particular object! We'll write our own classes later in the class, and then we'll write our own instance variables and instance methods as well. Things will be clearer then. The idea here is to show you first how to use objects and methods, and only later how to write your own classes with methods and the whole shebang.

ArrayList challenge exercise

Write a class in the org.progund.lists package called LoopChallenge with a main method which does the following:

  1. Check if there was any arguments to the main method (given on the command line)
    1. If there were no arguments, write a the following error message to the terminal "You must provide an argument".
    2. Exit the program (You can use the following code for that: System.exit(1); )
  2. If there were arguments, create an ArrayList and add every argument to the list.
  3. Write a message to the terminal indicating how many arguments were given.
  4. Loop through the list and print every element to the terminal
  5. Write a message saying "Here they come in reverse order"
  6. Loop through the list in reverse order and print every element to the terminal

In order to loop through an ArrayList in reverse order, you may use the following strategy:

Use a for-loop starting the loop variable i at list.size()-1 and loop as long as the loop variable is >=0. Use i-- as the change of the loop variable.

To access an element at a given index, use list.get(i) where list is the reference to the list, and i is the index you want to access.

Solutions

Expand using link to the right to see the full content.

System properties explained

Download this file here if you want to look at it. Remember that if you want to compile and run it, it must be in the correct directory structure!

 1 package org.progund.props;
 2 
 3 import java.util.Properties;
 4 
 5 public class ListSystemProps{
 6 
 7   public static void main(String[] args){
 8     Properties systemProps = System.getProperties();
 9     systemProps.list(System.out);
10   }
11 
12 }

What we see on line 8 Properties systemProps = System.getProperties(); is another way to get hold of an object. Here, instead of calling a constructor using the new operator, we ask a class to give us a reference to some object. In this particular case, we use the System class (in the java.lang package), to give us a reference to its properties objects. This is done by calling a method that belongs to the System class itself (we will later in the book see that such methods are called "class methods" or "static methods"). The call System.getProperties() can be explained like this: "Go to the System class, and call the method getProperties() there". That method returns a reference to a Properties object which is populated with key-value pairs for your system properties. We use the call to assign the reference to our variable systemProps (which is of type "reference to Propterties").

The whole statement Properties systemProps = System.getProperties(); can now be explained using the following words:

"Declare a Properties reference variable called systemProps and assign to it, the reference we get from calling System.getProperties()"

What our main method does here, is to create a reference variable called systemProps. But rather than creating a new object using new Properties(), we instead assign it a reference to an object that already exists (or is created by) the class java.lang.System.

On line 9 we have systemProps.list(System.out); which uses our local reference variable systemProps to call the method list on the object it refers to. The method list accepts an argument of where to list all the properties key-value pairs. We pass along a reference to the System.out object, which we have seen is connected to the standard out stream (the one we have used to print stuff to the terminal using println()).

So, our variable systemProps refers to an object of class properties. If we want that object to print its contents to our terminal, we send it the message list and we send along a reference to a place to print to. We could also say that we call the instance method list of the object and give the argument of where to print to.

From these two lines of code we learned two things: In a program we are writing ourselves, we can get a reference to an object some other class has or knows how to create. In our case, the System class offered the getProperties() method to programmers who wants a reference to an object that has all the system properties key-value pairs.

We also learned that we can now use our reference variable to send messages (or call instance methods) to an object. In our case, we sent the message list and we provided an argument telling the object what it could use to list its contents (in our case we sent along a reference to the System.out object, which is connected to our terminal).

Finally, some words on the import statement. We start our program source code with a package declaration which is only to give the compiler and JVM information on the location of our class and source code. Next we added an import statement saying import java.util.Properties;. This import statement was necessary, because we are using a class outside our own package, and outside the automatically imported java.lang package. The class Properties, as you can see from the import statement, is part of the java.util package. If we want to use the short name of the class (simply Properties) in our program, and we do want that!, we have to tell the compiler and runtime where to look for the Properties class!

If take the compiler as an example, without the import statement, it would get stuck while analyzing our code when it finds the Properties type on line 8. The compiler would look in the same directory as our file but wouldn't find any Properties class there. It would also look in the java.lang package (which is always imported automatically) but it wouldn't find it there either. The compiler would now give up and give as an error message about not finding the class Properties.

But with the import statement, the compiler would know where to look for the Properties class, since it says explicitly in the import statement that we will be using java.util.Properties. So the compiler has a path to the class Properties that it will use and the problem is solved!

Accessing individual property values explained

Download this file here if you want to look at it. Remember that if you want to compile and run it, it must be in the correct directory structure!

 1 package org.progund.props;
 2 
 3 import java.util.Properties;
 4 
 5 public class GettingValues{
 6   public static void main(String[] args){
 7     Properties systemProps = System.getProperties();
 8     String javaVersion = systemProps.getProperty("java.version");
 9     String operatingSystem = systemProps.getProperty("os.name");
10 
11     System.out.print("I'm running Java " + javaVersion);
12     System.out.println(" on a " + operatingSystem + " machine.");
13   }
14 }

In this program, we use the same technique as before to get the system properties from the System class. But instead of listing all the properties to the terminal, we are only interested in a few values. The values we are interested in are stored in the Properties object, that we got a reference to from System, using the following keys: "java.version" and "os.name".

A Properties object, as said before, stores key-value pairs. If we want to get a value, we ask for it using the key. So, if we want to get the value representing the Java version we are using on our system, we use the key "java.version". If we want the name of the operating system (according to Java), we use the key "os.name". but how do we use a key to get a value?

Look at lines 8 and 9. On line 8 we declare a String reference variable called javaVersion. We could have called it anything we like but we thought javaVersion was a good and descriptive name for a String with the java version as the text value. The statement on line 8 both declares this String reference variable and assigns to it the result of sending a message to the object referred to by systemProps.

The message (the instance method) we use is getProperty and the argument we send along is the key "java.version" as a String literal. So the instance method call is getProperty("java.version"). But how do we tell Java which Property object we want to send this message? Again, we use the dot separator. We write the name of our reference variable systemProps and a dot and then the instance method and arguments. You can think of this as meaning:

Go to the object referred to by systemProps and call the instance method getProperty on that object. Send along the argument of the key for the value we are interested in.

The same principle is applied on line 9.

A custom Properties object explained

Download this file here if you want to look at it. Remember that if you want to compile and run it, it must be in the correct directory structure!

 1 package org.progund.props;
 2 
 3 import java.util.Properties;
 4 
 5 public class CustomProperties{
 6   public static void main(String[] args){
 7     Properties favorites = new Properties();
 8     favorites.setProperty("favorite.color", "Pink");
 9     favorites.setProperty("favorite.programming_language", "Java");
10 
11     Properties systemProps = System.getProperties();
12     favorites.setProperty("favorite.encoding", systemProps.getProperty("file.encoding"));
13     System.out.println("These are a few of my favorite things:");
14     favorites.list(System.out);
15   }
16 }

Here we create our own Properties object using the normal way of calling a constructor for the object using the new operator keyword. The constructor we are using takes no arguments, hence the empty parentheses.

With a brand new, empty, Properties object, we can start storing our own key-value pairs. In this program we show you how to use the setProperty method to add a new key-value pair to a Properties object. Since a Properties object hold a collection of key-value pairs, adding a new entry must mean that we add both the key and the value to be stored. This is why the setProperty method takes two arguments! The first argument is the key, and the second argument is the value. In a Properties object, both the key and the value in each entry are references to Strings. So, when we add an entry for "favorite color" to our Properties object, we call the setProperty instance method using our variable favorites like this (as seen on line 8):

8     favorites.setProperty("favorite.color", "Pink");

The Properties object favorites refers to now has a new entry consisting of the key favorite.color and the value Pink. If we'd later wanted to retrieve the value for the property favorite.color, do you remember how to do that? The answer is to use the getProperty method like this: String favoriteColor = favorites.getProperty("favorite.color"); (and at the same time save the value using the favoriteColor String reference created in the same statement!).

Line 9 adds another key-value pair to the Properties object referred to by favorites. The really interesting thing in this program happens on line 12:

12     favorites.setProperty("favorite.encoding", systemProps.getProperty("file.encoding"));

As before, we use the favorites reference variable to add a key-value pair to the object referred to by favorites. But look closely at the second argument: systemProps.getProperty("file.encoding") which uses a method call as the value for the argument! As you can see, arguments are listed separated by a comma. In the simple example of adding the key "favorite.color" with the value "Pink", we simply listed two String literals separated by comma. Both arguments were evaluated to the reference address of the two String objects created by the literals. But on line 12, the second argument is not a String literal. It is a call to the getProperty method of the Properties object referred to by systemProps (created on line 11). The result of calling getProperty, as we've seen before, was a reference to a String representing the value associated with the key given as argument. This means that we can use this method call as an argument, where a String reference is expected!

From this we learn that expressions also can consist of method calls!

We could have broken up the statement on line 12 to several lines to make it more readable:

    String fileEncoding = systemProps.getProperty("file.encoding");
    favorites.setProperty("favorite.encoding", fileEncoding);

In the two lines above, we are first creating a String reference called fileEncoding and assigning it a reference to the value String we get from asking the systemProps object for the value stored with the key "file.encoding". On the next line, we use this String reference variable (fileEncoding) as the second argument when we store it using our favorites Properties reference.

So, once again, instead of first getting the "file.encoding" value and storing it using a String variable with the value from the getProperty method call, we can use the method call directly as an argument! This works because method calls can have a value and be used as expressions.

An argument that must be of type "reference to String" can take many forms. It can be a String literal such as "file.encoding", it can be a String reference variable like fileEncoding or it can be a method call to a method which returns a String reference such as in systemProps.getProperty("file.encoding")

On the last line of the main method, we ask our favorites Properties object to list itself on the standard output stream (our terminal), by sending it the message list(). How do we know that we sent that message to our specific object? We used the reference variable favorites and the dot separator: favorites.list(System.out); .

Using ArrayList explained

Download this file here if you want to look at it. Remember that if you want to compile and run it, it must be in the correct directory structure!

 1 package org.progund.lists;
 2 
 3 import java.util.ArrayList;
 4 
 5 public class NameList{
 6   public static void main(String[] args){
 7     ArrayList<String> nameList = new ArrayList<String>();
 8     nameList.add("Adam");
 9     nameList.add("Ana");
10     nameList.add("Bart");
11     nameList.add("Lisa");
12 
13     System.out.println("We now have " + nameList.size() + " names:");
14     System.out.println(nameList);
15 
16     if( nameList.contains("Bart") ){
17       System.out.println("The index of Bart is " + nameList.indexOf("Bart"));
18     }
19 
20     nameList.remove("Bart");
21     System.out.println("We now have " + nameList.size() + " names");
22 
23     if( nameList.contains("Bart") ){
24       System.out.println("Bart is still there!");
25     }else{
26       System.out.println("There is no Bart in the list any more.");
27     }
28 
29     System.out.println("Let's clear the list!");
30     nameList.clear();
31     System.out.println("We now have " + nameList.size() + " names");
32     if( nameList.isEmpty() ){
33       System.out.println("The list is now empty.");
34     }
35   }
36 }

On line 3, we have an import statement where we import the location of the ArrayList class. We are creating and using an ArrayList in this small program, so as usual we must have the include statement for that class, since it is not part of the java.lang</package>. Remember that only classes from the <code>java.lang package are imported automatically ("imported" means that the compiler and runtime system knows where to find them) from the Java API.

On line 7 we have:

7     ArrayList<String> nameList = new ArrayList<String>();

This is a standard declaration and initialization of a reference variable. We declare the variable nameList as being of type "reference to ArrayList", and we initialize this variable to refer to a newly created ArrayList. The new syntax in this code is the <String> part. As we said before, this is there to specify what kind of things we want to be able to store in the ArrayList. By specifying String, we will now only be able to store String references in the ArrayList referred to by nameList. This special syntax is called "generics". Generics was added to Java in version 5, and is there to provide some help for us programmers so that we don't do stupid things. By specifying what types can be stored in an ArrayList, we get help from the compiler javac to check that we don't happen to store references of other types in the list. It also lets us get elements from the list in a convenient way. If we only can store String references in an ArrayList declared as above, we know that we can get an element from the list and be sure that is is a String reference.

Prior to Java 5 and the introduction to Generics, we could store basically anything in an ArrayList but whenever we wanted to get an element from the list, we hade to cast (convert) it to the correct type. Thanks to Generics, we don't have to fiddle with type casts when getting elements from such a list anymore.

The lines 8-11 adds elements to the ArrayList:

 8     nameList.add("Adam");
 9     nameList.add("Ana");
10     nameList.add("Bart");
11     nameList.add("Lisa");

This is, as you see, done via the reference nameList and calls to the instance method add(). This is one of the cases where the compiler would help us if we made a mistake! If we had tried to add something other than a String reference to the list, the compiler wouldn't have let us do so, and would have complained about it.

Note that perhaps surprisingly, we say String references when we talk about what is stored in the ArrayList. Remember that the double quote separators, creates new String objects and have the value of the reference addresses of those objects (pretty much as if we'd called constructors instead).

When the program is running, the Java virtual machine (JVM) will create the String objects, and store only the references in the array. When we want to use one of the objects in the ArrayList, we use the reference to the object to use it. There is no way to access objects directly in Java. Objects are always accessed via references.

On line 13 we have

13     System.out.println("We now have " + nameList.size() + " names:");

Here we create and print some facts about our ArrayList object. We use the + concatenation operator to create the full text. The interesting part is in the middle, where we use our reference nameList to ask the object for its size (the number of elements currently in the list).

The perhaps most surprising part of this program comes on line 14:

14     System.out.println(nameList);

Here we call the println method on the out object in the class System as usual when we want to print something to the terminal. But this time, we don't give a String reference as an argument, but a reference to an ArrayList! And the thing which gets printed is:

[Adam, Ana, Bart, Lisa]

The thing which is printed is a nicely formatted list of elements in order, of the ArrayList. The surprising part, is that it seems like println knew how to convert the ArrayList to this nice thing. Part of the truth (we'll learn more details about this later in the book!) is that it is actually the ArrayList object which knows how to convert itself to a String. There is a method in every class which is called toString() where code for creating a nice String representation of the state of the object can be written. ArrayList has appropriate code inside its version of toString.

You should know, however, that when you later create your own classes, if you want to offer a nice version of toString(), you have to write code for that yourself.

What perhaps is less surprising is that the list is printed with the elements in the same order as they were inserted (added) to the list. This is so because each subsequent call to add() for a list, adds the new element at the end of the list.

On lines 16-18 we have:

16     if( nameList.contains("Bart") ){
17       System.out.println("The index of Bart is " + nameList.indexOf("Bart"));
18     }

Here we demonstrate the call of an instance method which returns a value of type boolean (true or false). Such a method call fits very well as the condition of an if-statement! If the method returns a boolean value, it can be used as an expression of boolean type. And the if-statement requires such a boolean expression in its test (between the parentheses). The method is called contains() and checks if some element exists in the list. Not if the exact same object is present in the list, but an object which is "equal" to the argument of contains(). For Strings, equality tests are easy to understand. Two Strings are considered equal if they contain exactly the same characters in the same order. On the lines above, we tested if there was any String in the list, whose characters were equal to "Bart" (and there was!).

Since the contains() method call returned true (gave us the answer true), the execution, when you ran it, entered the if block and it executed the statement System.out.println("The index of Bart is " + nameList.indexOf("Bart"));.

The meaning of that statement is that we create a text for our old friend println() by concatenating a String with the call to indexOf("Bart"). The result was:

The index of Bart is 2

So, if we want to get the position (index, indices start at 0 as with normal arrays) of an element, we can use a reference to the ArrayList object and send the message (call the instance method) indexOf() and provide a reference to some object to look for. If the ArrayList object can find the element, it returns the index as an int. But how does it find an element? The ArrayList actually will have to loop through all its elements and compare them with the object given as argument (the object to search for) again using the equals() method. So again, the object we search for, doesn't have to be exactly the same object whose reference is in the list. It is enough that an object reference leads to an object which is "equal" to that of the argument.

What if there are more than one object which is equal to the one we want the index of? Then we get the index of the first match using equals.

There is a method in ArrayList called lastIndexOf() which works in a similar way, but instead returns the greatest index (if it finds a match). Both methods returns -1 if no match is found.

On lines 20-21 we find:

20     nameList.remove("Bart");
21     System.out.println("We now have " + nameList.size() + " names");

First the element which matches "Bart" is removed from the list. Next we again print the size of the list. The result is, not surprising, that the list is now one element smaller than before!

On lines 23-27 we demonstrate an if-else statement, which checks if there is any element matching "Bart" in the list. If there is, a text indicating this is printed, otherwise a text telling us that there was no "Bart" in the list is printed:

23     if( nameList.contains("Bart") ){
24       System.out.println("Bart is still there!");
25     }else{
26       System.out.println("There is no Bart in the list any more.");
27     }

Since we only had one "Bart" String in the list, and it was removed, the latter message was printed.

After this, we clear the list. Calling clear() on an ArrayList via a reference removes all elements and the list is empty after that:

29     System.out.println("Let's clear the list!");
30     nameList.clear();
31     System.out.println("We now have " + nameList.size() + " names");

The last thing which happens in the program is that we show how you can use a reference to an ArrayList to ask the list if it is indeed empty. We use the call of isEmpty() as the boolean expression in an if-statement:

32     if( nameList.isEmpty() ){
33       System.out.println("The list is now empty.");
34     }

Method which checks some facts and returns a boolean (true or false) often have names like this. It makes the code easy to read and understand. The claim we want to test for validity is that the list "is empty". Giving the method the name isEmpty makes reading the code almost plain English: "If nameList is Empty...". This is a good naming scheme for methods which produce a boolean response.

ArrayList challenge suggested solutions

Version 1, simplest solution?

Download this file here if you want to look at it. Remember that if you want to compile and run it, it must be in the correct directory structure!

 1 package org.progund.lists;
 2 
 3 import java.util.ArrayList;
 4 
 5 public class LoopChallenge{
 6 
 7   private final static int NO_ARGUMENTS=1;
 8   public static void main(String[] args){
 9     if(args.length == 0){
10       System.err.println("You must provide at least one argument.");
11       System.exit(NO_ARGUMENTS);
12     }
13 
14     ArrayList<String> argList = new ArrayList<>();
15     for(String arg : args){
16       argList.add(arg);
17     }
18 
19     System.out.println("You gave " + args.length + " argument(s)");
20 
21     for(String arg : argList){
22       System.out.println(arg);
23     }
24 
25     System.out.println("Here they are in reverse order:");
26 
27     for(int i=argList.size()-1; i>=0; i--){
28       System.out.println(argList.get(i));
29     }
30   }
31 }

Comments on the solution above: On line 7 we declare a class variable to hold the argument to System.exit(). System.exit aborts the program and sends a return value to the operating system. Any value other than 0 means that the program failed somehow. We could have written System.exit(1) but if we have many error conditions represented by numbers, it would be hard to remember what kind of error they represented. Better to use a constant value declared as on line 7, rather than hard coded magic numbers that no one will remember what they stood for.

The statement private final static int NO_ARGUMENTS=1; declares an internal variable for the class, whose value cannot be changed. private means that this is an internal affair of the class (no code from other classes may use this variable), final means that this variable cannot have its value changed, static means "belongs to the class and not to any particular object of the class". Constants like this usually have names with only capital letters and underscore to divide parts of the name.

Lines 15-17 uses a "for-each loop" to add all elements from the args array to the ArrayList object:

15     for(String arg : args){
16       argList.add(arg);
17     }

Lines 27-29 loops through the ArrayList in reverse order, starting at the last index all the way down to index 0:

27     for(int i=argList.size()-1; i>=0; i--){
28       System.out.println(argList.get(i));
29     }

Explanation of the for-loop: int i=argList.size()-1 initializes the loop variable i to the last index. Remember, since indices start at 0, the highest index is always the same as the size of the list minus one. i>=0 is the condition of the for-loop. We are going down but we should stop at the first index, namely 0. i-- is the change part of the for-loop. We want to decrease i after each iteration, and you can write like this to decrease an integer with one. It is the same as the expression statement i=i-1; but no one uses that, since i-- is so much shorter...

In the body of the loop we have: System.out.println(argList.get(i));. The interesting part here is of course argList.get(i) which is a simple call to the instance variable get() in the ArrayList class. The method takes one argument, the index for which element we want to access.

Version 2, harder but less code:

Download this file here if you want to look at it. Remember that if you want to compile and run it, it must be in the correct directory structure!

 1 package org.progund.lists;
 2 
 3 import java.util.List;
 4 import java.util.Arrays;
 5 import java.util.Collections;
 6 
 7 public class LoopChallengeVersion2{
 8 
 9   private final static int NO_ARGUMENTS=1;
10   public static void main(String[] args){
11     if(args.length == 0){
12       System.err.println("You must provide at least one argument.");
13       System.exit(NO_ARGUMENTS);
14     }
15 
16     List<String> argList = Arrays.asList(args);
17 
18     System.out.println("You gave " + args.length + " argument(s)");
19 
20     for(String arg : argList){
21       System.out.println(arg);
22     }
23 
24     System.out.println("Here they are in reverse order:");
25 
26     Collections.reverse(argList);
27 
28     for(String arg : argList){
29       System.out.println(arg);
30     }
31   }
32 }

First of all, we don't use ArrayList directly in this version. Instead we use something called an interface, and the interface is called List. That interface describes what we can do with different kinds of list (for instance ArrayList objects). We'll talk a lot more about interfaces in coming chapters, so don't worry if you don't follow us completely. We also use some utility classes from the java.util package. Together, we are using two classes and one interface from that package so we import it like this:

3 import java.util.List;
4 import java.util.Arrays;
5 import java.util.Collections;

Our list reference variable is in this version not explicitly an ArrayList, but rather has the more general type List. This is useful, because we can now use a utility class method from the Arrays class to convert the array args to a List like this (on line 16):

16     List<String> argList = Arrays.asList(args);

The Arrays class has a lot of useful class methods (methods we don't need object references to use, we call them directly using the class name!) for manipulating arrays. This particular message creates an object of interface type List (for instance an ArrayList object) from an array. This way, we don't have to iterate through the array and add each element to our list object.

Once again, you don't have to understand all this yet! We are showing it just as a teaser for what comes in next chapters. We want to show you code that contains stuff you don't have seen yet, and our hope is that you will at least recognize parts from this code when we introduce more stuff in later chapters.

On line 26, we use another useful utility class from the java.util package, Collections. There are many types of collections but List is one type of collection. The Collections utility class contains many useful class methods for manipulating various kinds of collection objects. Here, we use the class method reverse(), which takes a list and reverses the order of all the elements! This allows us to use a standard for-each loop again to print the elements in reversed order:

26     Collections.reverse(argList);
27 
28     for(String arg : argList){
29       System.out.println(arg);
30     }

Note that the list is now still reversed, and if we wanted to use it in the original order, we'd have to reverse it again before that use.

The Object Oriented suggested solution consists of two files. It is here just as a reference for you to read and try to understand. It is a great reading exercise to prepare you for the next chapters to come! You see, here we create our own class to do the dirty work, which allows us to keep the main method clean and short, and quite easy to read! Enjoy the reading!

File: org/progund/lists/LoopChallengeOOVersion.java:

Download this files here (LoopChallengeOOVersion with the main method) and here (ArgumentHelper class, used in the main of the LoopChallengeOOVersion class if you want to look at it. Remember that if you want to compile and run it, it must be in the correct directory structure!

 1 package org.progund.lists;
 2 
 3 public class LoopChallengeOOVersion{
 4   public static void main(String[] args){
 5     ArgumentHelper argHelper = new ArgumentHelper(args);
 6     if(argHelper.hasArguments()){
 7       argHelper.start();
 8     }else{
 9       System.err.println(argHelper.errorMessage());
10     }
11     System.exit(argHelper.exitCode());
12   }
13 }

File: org/progund/lists/ArgumentHelper.java:

 1 package org.progund.lists;
 2 
 3 import java.util.ArrayList;
 4 
 5 public class ArgumentHelper{
 6 
 7   private static final int NO_ARGUMENTS = 1;
 8 
 9   private String[] args;
10   private ArrayList<String> argList;
11 
12   public ArgumentHelper(String[] args){
13     this.args = args;
14     init();
15   }
16 
17   private void init(){
18     if( hasArguments() ){
19       argList = new ArrayList<String>();
20       for(String arg : args){
21         argList.add(arg);
22       }
23     }
24   }
25   public boolean hasArguments(){
26     return args.length != 0;
27   }
28 
29   public void start(){
30     if( hasArguments() ){
31       System.out.println("You gave " + argList.size() + " arguments");
32       printArgs();
33       printReverse();
34     }
35   }
36 
37   private void printArgs(){
38     System.out.println("These were the arguments:");
39     for(String arg : argList){
40       System.out.println(arg);
41     }
42   }
43 
44   private void printReverse(){
45     System.out.println("Here they are in reverse order:");
46     for(int i = argList.size()-1; i>=0; i--){
47       System.out.println(argList.get(i));
48     }
49   }
50   public int exitCode(){
51     if( hasArguments() ){
52       return 0;
53     }else{
54       return NO_ARGUMENTS;
55     }
56   }
57   public String errorMessage(){
58     if ( !hasArguments() ){
59       return "You must provide at least one argument!";
60     }
61     return "";
62   }
63 }

Links

Tutorials etc:

The Java API online documentation

Description

You might (rightfully) wonder how we could know what classes exist in the Java API and, perhaps even more so, how we knew what constructors and instance methods existed in those classes. The answer is, that we cheated and looked in the API documentation!

The thing is, that Java comes with quite an extensive library, what is often called the Java API. There are so many classes included in the API and many of the classes are quite large, so that no one is expected to learn all the classes and how to use them by heart. For this, the good people at Oracle have created an online API where you can explore the API and examine the classes.

The API is divided in packages, and the packages include related classes (and so called interfaces, which we haven't learned about yet). To examine for instance the ArrayList class (in the java.util package) you can navigate to the java.util package and click on the ArrayList class. You are then presented with a web page describing the ArrayList class. First on such a class page in the API documentation is a descriptive text about the class, its purpose and sometimes some example uses. Next the public parts of the class (public parts are such parts which you can use as a programmer) such as variables (fields), constructors (if any) and methods.

In this section we show you how to find the Java online documentation, how to navigate it and how to read about constructors for some classes and about instance methods. Later in the course, we will learn that we can create such documentation pages in HTML ourselves using a certain type of comments directly in our source code.

Videos

  • Introduction to the online documentation eng swe
  • How to read about a class in Java's API documentation eng swe
  • Documentation for ArraryList eng swe
  • Documentation page for Properties eng swe
  • Documentation page for System eng swe

Exercises

  1. Navigate to the String documentaion page
    How many constructor does the documentation present? How many have you used?
  2. Still on the page for String, find the length method. What type of value does it return? What does the value represent?
  3. Navigate to the java.util.ArrayList class page.
    How many methods called remove can you find? How do you think Java knows which one you are using if you use one of them?
  4. Still looking at the documentation page for ArrayList read about the remove(int index) method. When an element at an index is removed, what happens to the rest of the elements?

Solutions

Expand using link to the right to see the full content.

  1. 15 (in the Java version 7 documentation) constructors are listed. You have only used on, the one which takes a String argument (and you have used the double quotes to create Strings - perhaps that should count as a constructor, even if it is unique to String).
  2. It returns an int representing the length of the String (all characters including white space and special characters)
  3. There are two versions of the remove method. Having more than one method with the same name is called overloading (if you like technical words). The java compiler will decide which one you mean based on first the name, then the types of the variables. If you call myList.remove(3) the argument 3 has type int, so the compiler will understand which method you mean by matching the name and type of arguments to the corresponding method in the ArrayList class definition.
  4. When an element at an index is removed, any elements at greater indices (you can think of them as elements to the right of the element to be removed) are shifted one position to the left:
    Example:
    Before if the list has the following Strings:
    ["I", "am", "Groot"]
    it will become like this if you call remove(1) (remove the element at index 1 - "am")
    ["I", "Groot"]

Section links (API Documentation)

Read the Java API documentation for a list of constructors and instance methods and more for the various classes used in the exercises:

Questions and Answers

Expand using link to the right to see the full content.

Q: "Objects are entities with data and behavior, you say. How is the data actually stored in an object and how do we invoke an object's behavior?"
The data is stored inside the object in the memory space for the object in the JVM's so called "heap memory". This happens when the program is running and the code of the program creates a new object somehow (usually be calling a constructor in the class which describes obects of this type and this is done using the operator new). The data inside an object can also be called "the object's state". The code in the class describing objects of a particular type declares variables to store the state of the object. Normally, this is done using the keyword private, which effectively hides the variable name from uses by code in other classes (code that use and manipulate the objects). To change or use the state of an object, one typically invoke one of the instance methods of the object. Instance methods are methods also written in the class describing a particular type of objects, and they may access the instance variables (even if they are marked private because code in the same class is the only code that have access to private stuff).

In order to invoke some behavior, i.e. calling an instance method, for an object, you need to have a reference variable which refers to the object you want to use. A reference variable is a variable whose type is the same as the type of the object (often the class of the object). The reference variable is your handle to the object in the heap memory. Invoking a method on an object is done by using the reference variable and the dot separator and the name of the instance method together with any arguments the method might need.

You have already used objects via reference variable, perhaps without knowing so. When you used the System.out.println("Hello"); statement, you were actually using the reference object out (which belongs to the class System). Via the reference variable out, you invoked the instance method println(String str) for the object which out referred to.

In coming chapters, we will learn how to write our own classes. Hopefully things will get clearer then, when you yourself write the code for instance variables and instance methods. For now, you can think of classes as compilation units for a program. This units (classes) describe common state variables and common instance methods for a type of objects. Classes are written once and used many times. You use a class as the type of reference variables you use in a program. Reference variables are then assigned references to objects, usually as the result of calling the constructor of the class that describes a certain type of objects.

Q: "Can you say that classes, then, are descriptions of objects of the same type?"
That's one way of putting it. But beware that not all classes are used as the blueprint or description of objects! For instance, you have already learned that a small Java program requires at least one class, the one containing the main method. It is not sure that such a class will be used for creating objects (but it is possible).

Many Java books define classes simply as the blueprint for similar objects. While this is true most of the time, it is not true in every case. You have, for instance, used the System class (because it's the one which has the out reference variable we use for printing stuff to the standard output stream). The System class can't even be instantiated (you cannot create objects using System as the type or description). There are actually quite a few classes like that in the Java standard API. Another example is the class Math. You use the class Math because it offers a lot of mathematical methods directly to the programmer. You don't have to create a Math object in order to invoke for instance the sqrt (square root) method. In fact, you cannot create an instance of Math. The reason for this design decision is probably convenience (smoother to invoke a method directly using the class name) and the fact that it doesn't make sense to have many objects representing "Mathematics".

Q: "You say that some classes can't be instantiated, i.e. you cannot create objects from them. What keeps some programmer from simply calling the constructor using the operator new on for instance the System class?"
It is done using the private keyword. Anything in a class marked as private cannot be used from outside the class itself. You have seen what a constructor looks like. Do you remember? Usually a constructor looks like this:

public ClassName(){
  //some clever code which initializes the state of the ClassName
  //object which is being created here... 
}

The pattern is public followed by ClassName (the name of the class) and parentheses with arguments (if any) to be used in the constructor body for initialization. But what if you substitute private for public? Then the constructor itself cannot be called from outside the class! This means that no one can create objects of this class (provided there are no public constructors at all in the class). This is what the only constuctor in System looks like:

    /** Don't let anyone instantiate this class */
    private System() {
    }

This is taken directly from the source code of java.lang.System. Note the comment in the source code!

Q: "You say instance methods must be invoked using a reference to some object. Yet you say that there are methods in for instance Math but we cannot create objects of type Math. How can this be?"
That's a very good observation! Instance methods are always only relevant for some object and you need to invoke them using a reference to the object which you want to use. But methods in the class Math, for instance, are not instance methods. I'm sorry to break it to you, but there are actually two types of methods. Methods that you can call without objects or references are called "class methods" (because they belong to the class itself and not any particular object) or "static methods" (because they are written with the keyword static like the good old public static void main(String[] args). The method sqrt in class Math for instance, is defined like this:

public static double sqrt(double a){
  //some clever code which calculates the square root of "a" 
}

Note the static keyword! It means that this method should be called using the class name such as:

  double c = Math.sqrt( a*a + b*b );
}

Q: "But if static methods, or class methods as you also call them, are more convenient than instance methods, why do we need instance methods?"
Again, a great question, but a little harder to answer. The thing about static methods, is that they are not very common in typical Java program (if you don't count methods from simple programs in Java text books). Programming in the object oriented style means that we package data and behavior together in objects and we let the objects do all the work in our program. Static methods cannot operate on instance variables (since they cannot know if there are any instances, and which instance to use if threre are). So static methods can only operate on the data we send to them as arguments (and data that is stored directly in the class). This is the opposite of the object oriented way of thinking! We don't want to manage a lot of data and send them to methods. We'd rather talk about objects and let the objects keep track of their data, and we humbly ask the objects to do some work for us, taking their state into account.

Static methods are mainly there as convenience methods for performing rather mechanical and static work, like calculating the square root of some number. Objects, on the other hand, are much more lifelike creatures. A program for a computer game, for instance, might have several Player objects (perhaps running around in a maze trying to find a treasure). All Player objects share the same characteristics but they are individuals. One Player object might be green and very fast, while another Player object might be Pink and not so fast (but has the ability to jump over large rocks). All players are described in the Player class, but their state varies. We can invoke the same type of behavior using the instance methods described in the class on them, but the result would be different depending on their state. Invoking the run() method on the first player would result in fast movement but if we invoke the same behaviour (run) on the second player, the movement wouldn't be so fast. This could be done using a private speed variable which keeps track of the maximum speed for particular Player objects. The first player had a large number stored in its speed variable while the second player had a smaller number in its speed variable. But the actual variables are private and hidden from the users of the Player class (the programmer writing the logic of the game). The program using the Player class uses reference variables to invoke behavior on a Player object like calling the run method on one of them. The object itself now knows how to run (and how fast it can run) which lets our programmer focus on things on a much higher level of abstraction.

Q: "The String class seems to be very useful. There are lots of program which handle text. But it seems a little special. Could you say something about what makes the String class and objects of type String (reference to String, as you seem to prefer to say)?"
The String class has some properties which makes it a little different from other classes. The first thing that comes to mind here, is that we can create new String objects simply by typing a text string inside quotes. That's very untypical for object creation. The reason for Java to allow this weird behavior is that it actually makes the creation of String objects very simple. And since String objects are so common in programs, why not offer a simple way to create them? You can use constructors for creating String objects too. But there is a subtle difference between a String created like this: String name = "Adam"; and a String created like this String name = new String("Adam");. The difference is very subtle but very important to understand later in the course (or if you keep studying Java). Strings created using the double quotes are re-used. By re-used, we mean that in a program where two Strings with the exact same text are created using double quotes doesn't actually create two different String objects. The JVM will discover that there already exists a String object with the same text as the second object created with quotes. So any reference variables referring to the String object created with quotes, will refer to the same object in the memory:

  String myName   = "Adam";
  String yourName = "Adam";
}

In the code above, threre is only one String object created. Both myName and yourName now refers to that same object in the memory. Such objects are said to be put in the "string constants pool". If you really need two different String objects with the same text, for some reason, you would have to use the constructor and the operator new for at least one of them. Using the constructor for any class of object, always guarantees a new distinct object.

At this point you don't have to care about this subtle difference so much, but it would be wrong for us not to mention it at least. If you keep using or studying Java, however, these things might get important for you to understand the exact behavior of a program written in Java.

Another thing that makes String convenient to use is that it is part of the java.lang package. The special thing about that package is that you can use classes in that package directly without having to import their path to the program using the import statement. You may think of it as the java.lang package always automatically (implicitly) being imported.

Lastly, there is another subtle thing about the String class and its objects. Objects of type String are what is called immutable. That simply means that you cannot change the state of a String object (you cannot change the text of a String object). If you call, for instance, the toUpperCase() instance metod of a String, you might think that you change all the letters in the String to upper case. You don't. What happens is that the method creates a new String (with the same letters but all upper case) and returns a reference to that object to you. The old object will get discarded from memory automatically:

  String name = "Adam";
  name = name.toUpperCase();
}

In the code above, first a String is created representing the text "Adam" and the variable name is assigned the reference to it. On the second line, the instance method toUpperCase() creates a new String object representing "ADAM" and returns a reference to that object. The reference to this new object is assigned to name. The first object (representing "Adam") is now long gone and forgotten about. It will be "garbage collected" by the JVM since there are no references to it any more, so it can't be used anyway.

Q: "Phew! Strings seem to be complicated creatures. Should I worry?"
Don't worry. This is an introductory course and we will not use these special cases against you! We are only telling you about them so that we don't feel that we've kept secrets from you. If you don't understand these subtleties now, you don't have to worry. Hopefully they will become clearer when you have read more chapters and seen more lectures later on. Why not revisit this explanation after a few more lectures? However, we will not require that you understand and remember these quirks after the course. Topics we feel are very important will always be part of lectures and/or exercises. These Questions and Answers are for the curious and ambitious student who always want to learn more!

Q: "Packages seems to be an important concept in Java, because every class seems to belong to a package. When we write our own classes, like in the exercises, the package declaration always matches the path to the source code (and binary class) file for the class (only that dots are used to separate directories where the shell would use a forward slash). But when we import for instance java.util.Properties, I don't understand where the path "java/util/Properties.class" would lead? Is there really directories somewhere for the java api packages and their classes?
That was very observant of you! Yes, the packages in the API (like java.lang, java.util and all the rest) are actually also paths to the compiled versions of the classes in the packages. The only difference, is that the whole API (with all its directories for packages and all the class files in those directories) are packaged together in a file called rt.jar. If you think about it, how could it work to use java.lang.String for instance, if there was no compiled class file called String.class on your system? And how could the compiler and JVM find it if the package didn't symbolize a path with directories, like when we create our own classes?

When you install the JDK (Java Development Kit), you get the API as a part of the installation (otherwise we couldn't use String or Properties etc). The part which actually contain all these API classes is a kind of zip file (compressed archive file) with a large directory structure inside it. The file is called rt.jar (jar is a Java type of compressed archive file format).

To prove we are not lying to you we'll show you that the directory structure is there, using some bash command trickery:

$ ls /usr/lib/jvm/java-7-openjdk-amd64/jre/lib/rt.jar
/usr/lib/jvm/java-7-openjdk-amd64/jre/lib/rt.jar

$ file /usr/lib/jvm/java-7-openjdk-amd64/jre/lib/rt.jar
/usr/lib/jvm/java-7-openjdk-amd64/jre/lib/rt.jar: Java Jar file data (zip)

$ jar tf /usr/lib/jvm/java-7-openjdk-amd64/jre/lib/rt.jar | grep '/System.class'
java/lang/System.class

$ jar tf /usr/lib/jvm/java-7-openjdk-amd64/jre/lib/rt.jar | grep '/Math.class'
java/lang/Math.class

What we did there, was to list the rt.jar on a computer with Java 7 installed. Next, we used the file command to investigate what kind of file the rt.jar was. The answer was "Java Jar file data (zip)" (file is a very capable command for investigating files!). After that, we used the jar utility command (also included in the JDK) to list the files in the rt.jar, but since there are thousands of classes there, we filtered using grep the result for some familiar classes mentioned above. As you can see, the System.class was in the directory java/lang/System.class and the Math.class file was in the same directory. The directories correspond the the package names! java.lang.Math corresponds to the compiled class file found in java/lang/Math.class in the rt.jar archive.

Q: "In one of the more complicated solution suggestions to the Loop Challenge exercise, you were using List instead of ArrayList. You said something about List not being a class but something called an interface. What is the difference between a class and an interface?"
We will talk a lot about interfaces in a chapter to come, but since you ask already, I'll try to be brief and explain some basic differences between classes and interfaces. As usual, you don't have to understand this yet, since we haven't gotten to the Interfaces chapter yet, but here goes anyway!

A class can define both instance variables for storing the state of objects to be created using the class and instance methods. Classes are in this regard quite closely related to objects. You can use a class to create an object. Interfaces (in the most common case) only concern themselves with describing the behavior (instance methods) of a group of objects. Interfaces describe what messages (what methods can be called) for a related type of objects. So interfaces also define a type of objects. But interfaces do this in a very abstract way, as they only describe the names, return types and arguments of methods for the type. Interfaces don not define the code for what the methods actually should do, just that they exist. An interface, then, is a construct much less related to specific classes of objects, since we use them when we only care about what methods exist for objects of an interface type, and how to use these methods.

List is an interface describing the methods common to different sorts of lists. ArrayList is a concrete type of list, described in a class. But the class ArrayList is said to implement the List interface, which means that all the methods abstractly described in List exist "for real" in the ArrayList class.

This construct allows us to declare references of type List so that we only care about what messages we can send to the actual object referred to (and the signature of the methods). If we use a List reference variable to refer to some List type object, the actual object may very well be an ArrayList (or some other list). We don't have to worry about that, since we will only send the messages (call the methods) declared in the List interface. You could, in this sense, say that it is easier to program against an interface type, than against a concrete (class) type.

In the actual example code where you found the use of List, the reference was assigned like this:

List<String> argList = Arrays.asList(args);

The asList() method in the Arrays class (by the way, a static method) takes as argument an array and converts it into an object of interface List type, and returns the reference. The actual object created most certainly is an ArrayList but we don't care, since we are only using the for-each loop to traverse the list in our program anyway. List type objects can be used in for-each loops, which was what we wanted to do in our program.

Q: "Talking about advanced solutions to challenges, the org/progund/lists/ArgumentHelper.java class, used in the suggested solution to the LoopChallenge in this chapter, the object oriented version, has a lot of instance methods, I guess. But why are some of them marked as private and some marked as public?"
We will talk a lot more about so called "access modifiers" (public and private for instace) in the next chapter, but in short private means "can only be used by code in this class". So only code in the ArgumentHelper class may call any of the private methods in the same class. On the other hand, public means that code from any class may call it. The ArgumentHelper class is used to create an object in the main method of the LoopChallengeOOVersion class. Code in this class can only call the public instance methods of the ArgumentHelper object.

Methods that are of no concern or use directly to users of objects should be declared as private (to keep people from using them or even knowing about them). The public methods in a class are what users of objects of the class see and can use. The public methods of an object can be said to be the "programming interface" to the object. The programming interface is what you can do with an object. As you saw in the solution, some of the public methods needed to get help from other methods but sometimes such helper methods are not meant to be part of the public interface of objects created from the class. So we hide them from users of the objects, which makes our objects easier to use. The fewer public methods an object has, of course, the easier it is to use and understand the object's capabilities.

More on this in coming chapters!

Chapter Links

External links

Books this chapter is a part of

Programming with Java book

Book TOC | previous chapter(Control flow - Exercises) | next chapter