In this section we will introduce some of the key elements of the Java language by describing the details of a small program. We will look at how a program is organized and what the various parts do. Our intent is to introduce important language elements, many of which will be explained in greater detail in later sections.
The program we will study is a Java version of the traditional HelloWorld program— ’’traditional’’ because practically every introductory programming text begins with it. When it is run, the HelloWorld program (Listing 1.5.1) just displays the greeting “Hello, World!” on the console.
Try the Hello World program below.
Activity1.5.1.
Run the following code. Try changing the greeting to "Hola!" and run again.
Subsection1.5.2Comments
The first thing to notice about the HelloWorld program is the use of comments. A comment is a non-executable portion of a program that is used to document the program. Because comments are not executable instructions they are just ignored by the compiler. Their sole purpose is to make the program easier for the programmer to read and understand.
The HelloWorld program contains examples of two types of Java comments. Any text contained within /* and */ is considered a comment. As you can see in HelloWorld, this kind of comment can extend over several lines and is sometimes called a multiline comment. A second type of comment is any text that follows double slashes (//) on a line. This is known as a single-line comment because it cannot extend beyond a single line.
When the compiler encounters the beginning marker (/*) of a multiline comment, it skips over everything until it finds a matching end marker (*/). One implication of this is that it is not possible to put one multiline comment inside of another. That is, one comment cannot be nested, or contained, within another comment. The following code segment illustrates the rules that govern the use of /* and */:
/* This first comment begins and ends on the same line. */
/* A second comment starts on this line ...
and goes on ...
and this is the last line of the second comment.
*/
/* A third comment starts on this line ...
/* This is NOT a fourth comment. It is just
part of the third comment.
And this is the last line of the third comment.
*/
*/ This is an error because it is an unmatched end marker.
As you can see from this example, it is impossible to begin a new comment inside an already-started comment because all text inside the first comment, including /*, is ignored by the compiler.
Definition1.5.2.Comment.
Any text contained within /* and */, which may span several lines, is considered a comment and is ignored by the compiler. Inserting double slashes (//) into a line turns the rest of the line into a comment.
Multiline comments are often used to create a comment block that provides useful documentation for the program. In HelloWorld, the program begins with a comment block that identifies the name of file that contains the program and its author and provides a brief description of what the program does.
For single-line comments, double slashes (//) can be inserted anywhere on a line of code. The result is that the rest of the line is ignored by the compiler. We use single-line comments throughout the HelloWorld program to provide a running commentary of its language elements.
Principle1.5.3.PROGRAMMING TIP: Use of Comments.
A well-written program should begin with a comment block that provides the name of the program, its author, and a description of what the program does.
Subsection1.5.3Program Layout
Another thing to notice about the program is how neatly it is arranged on the page. This is done deliberately so that the program is easy to read and understand.
In Java, program expressions and statements may be arranged any way the programmer likes. They may occur one per line, several per line, or one per several lines. But the fact that the rules governing the layout of the program are so lax makes it all the more important that we adopt a good programming style, one that will help make programs easy to read.
So look at how things are presented in HelloWorld ( Listing 1.5.1). Notice how beginning and ending braces, { and }, are aligned, and note how we use single-line comments to annotate ending braces. Braces are used to mark the beginning and end of different blocks of code in a Java program and it can sometimes be difficult to know which beginning and end braces are matched up. Proper indentation and the use of single-line comments make it easier to determine how the braces are matched up.
Similarly, notice how indentation is used to show when one element of the program is contained within another element. Thus, the elements of the HelloWorld class are indented inside of the braces that mark the beginning and end of the class. And the statements in the main() method are indented to indicate that they belong to that method. Use of indentation in this way, to identify the program’s structure, makes the program easier to read and understand.
Principle1.5.4.PROGRAMMING TIP: Use of Indentation.
Indent the code within a block and align the block’s opening and closing braces. Use a comment to mark the end of a block of code.
Subsection1.5.4Keywords and Identifiers
The Java language contains 50 predefined keywords ( Table 1.5.5). These are words that have special meaning in the language and whose use is reserved for special purposes.
Table1.5.5.Java keywords. Those with * are not used.
abstract
continue
for
new
switch
assert
default
goto*
package
synchronized
boolean
do
if
private
this
break
double
implements
protected
throw
byte
else
import
public
throws
case
enum
instanceof
return
transient
catch
extends
int
short
try
char
final
interface
static
void
class
finally
long
strictfp
volatile
onst*
float
native
super
while
The keywords used in the HelloWorld program (Listing 1.5.1) are: class, extends, private, public, static, and void.
Keywords cannot be used as the names of methods, variables, or classes. However, the programmer can make up their own names for the classes, methods, and variables that occur in the program, provided that certain rules and conventions are followed.
The names for classes, methods, and variables are called identifiers, which follow certain syntax rules:
Principle1.5.6.Identifier.
An identifier must begin with a capital or lowercase letter and may be followed by any number of letters, digits, underscores (_), or dollar signs ($). An identifier may not be identical to a Java keyword.
Names in Java are case sensitive, which means that two different identifiers may contain the same letters in the same order. For example, thisVar and ThisVar are two different identifiers.
In addition to the syntax rule that governs identifiers, Java programmers follow two style conventions when naming classes, variables, and methods.
Class names in Java begin with a capital letter and use capital letters to distinguish the individual in the name— for example, HelloWorld and TextField.
Variable and method names begin with a lowercase letter but also use capital letters to distinguish the words in the name— for example, main(), greeting, greet(), getQuestion(), and getAnswer().
These conventions make it is easier to distinguish the different elements in a program— classes, methods, variables— just by how they are written. (For more on Java style conventions, see Appendix A.).
Another important style convention followed by Java programmers is to choose descriptive identifiers when naming classes, variables, and methods. This helps to make the program more readable.
Principle1.5.7.PROGRAMMING TIP: Choice of Identifiers.
To make your program more readable, choose names that describe the purpose of the class, variable, or method.
Subsection1.5.5Data Types and Variables
A computer program wouldn’t be very useful if it couldn’t manipulate different kinds of data, such as numbers and strings. The operations that one can do on a piece of data depend on the data’s type. For example, you can divide and multiply numbers, but you cannot do this with strings. Thus, every piece of data in a Java program is classified according to its data type.
Broadly speaking, there are two categories of data in Java: objects and primitive data types. Java has many different types of built-in objects, in addition to those objects defined by programmers, Two built-in objects we encounter in this chapter are the String and PrintStream objects.
Java’s primitive types include three integer types, three real number types, a character type, and a boolean type with values true and false. The names of the primitive types are keywords likeint for one integer type, double for one real number type, and boolean.
As we noted in Chapter 0, a variable is a named storage location that can store a value of a particular type. You can think of a variable as a special container into which you can place values (Figure 1.5.8), but only values that fit into that type of variable . For example, an int variable can store values like 5 or -100. A String variable can store values like “Hello”.
In the HelloWorld class (Listing 1.5.1), the instance variable greeting (line 8) stores a value of type String. In the main() method, the variable helloworld is assigned a HelloWorld object (line 16).
A literal value is an actual value of some type that occurs in a program. For example, a string enclosed in double quotes, such as "Hello, World!", is known as a String literal. A number such as 45.2 would be an example of a literal of type double, and -72 would be an example of a literal of type int.
Our HelloWorld program contains just a single literal value, the "HelloWorld!" String.
Subsection1.5.6Statements
A Java program is a collection of statements. A statement is a segment of code that takes some action in the program. As a program runs, we say it executes statements, meaning it carries out the actions specified by those statements.
In our HelloWorld program (Listing 1.5.1), statements of various types occur on lines 8, 11, 15, 16, and 17. Notice that all of these lines end with a semicolon.
Principle1.5.9.JAVA LANGUAGE RULE: Semicolons.
In Java statements must end with a semicolon. Forgetting to do so would cause a syntax error.
A declaration statement is a statement that declares a variable of a particular type. In a Java program, a variable must be declared before it can be used.
Principle1.5.10.JAVA LANGUAGE RULE: Variable Declaration.
In Java, all variables must be declaraed before they can be used. Failure to do so would cause a syntax error.
In its simplest form, a declaration statement begins with the variable’s type, which is followed by the variable’s name, and ends with a semicolon:
Type VariableName ;
A variable’s type is either one of the primitive types we mentioned, such as int,double, or boolean, or for objects, it is the name of the object’s class, such as String or HelloWorld. Here are some examples:
HelloWorld helloworld;
int num1;
int num2;
The first declaration declares a variable namrd helloworld of type HelloWorld. The next two declarations declare int variables named num1 and num2.
What’s the purpose of declaration statements? Without going into too much detail at this point, declaring a variable causes the program to set aside enough memory for the type of data that will be stored in that variable. So in this example, Java would reserve enough space to store an int value, such as 25 or 1000.
An assignment statement is a statement that assigns a value to a variable — i.e., stores a value in the variable’s memory location. An assignment statement uses the equal sign (\(=\)) as an assignment operator. In its simplest form, an assignment statement has a variable on the left hand side of the equals sign and some type of value on the right hand side. Like other statements, an assignment statement ends with a semicolon:
VariableName =Value ;
Principle1.5.11.JAVA LANGUAGE RULE: Assignment Operator.
In Java, the equal sign (=) is used as the assignment operator.
When it executes an assignment statement, Java will first determine what value is given on the right hand side and then assign that value to the variable on the left hand side. For example, consider these three assignment statements:
num1 = 50; // (a) Assign 50 to num1
num2 = 10 + 15; // (b) Assign 25 to num2
num1 = num2; // (c) Copy num2's value (25) into num1
In (a) the value on the right hand side is 50. So 50 gets stored in num1, resulting in the situation shown in the top row of Figure 1.5.12.
In (b) the value on the right hand side is 25, the result of adding 10 and 15. So 25 gets assigned to num2, leading to the situation shown in in row two of the figure. In (c) the value on the right hand side is 25, the value of num2, which is stored in num1, as depicted in row three of the drawing.
The last of these assignments, (c), has variables on both sides of the equal sign, which can be confusing to beginning programmers. It might look like we’re saying that num1equalsnum2. But, remember, the equal sign is the assignment operator. So, this statement is saying: take the value stored in num2 and store it in num1.
Observation1.5.13.
Try running the program below.
Activity1.5.2.
Run the following code. Click on the "Show Code Lens" button and then the Next button to step through the code.
Another kind of Java statement is the method-call statement, as in these examples from the HelloWorld program (Listing 1.5.1):
In the first statement we are calling the greet() method, which will perform certain actions for us. In the second, we are calling the system’s println() method to display a greeting on the computer screen. We will discuss these kinds of statements in greater detail as we go along.
Finally, notice that we can use curly braces to group one or more statements into a sequence as in the definition of the main() method.
The manipulation of data in a program is done by using some kind of expression that specifies the action. An expression is Java code that specifies or produces a value in the program. For example, if you want to add two numbers, you would use an arithmetic expression, such as \(num1 + num2\text{.}\) If you want to compare two numbers, you would use a relation expression such as \(num1 \lt num2\text{.}\) As you can see, these and many other expressions in Java involve the use of special symbols called operators. Here we see the addition operator (\(+\)) and the less-than operator (\(\lt\)). We have already talked about the assignment operator (\(=\)).
Java expressions and operators have a type that depends on the type of data that is being manipulated. For example, when adding two int values, such as \(5 + 10\text{,}\) the expression itself produces an int result. When comparing two numbers with the less than operator, \(num1 \lt num2\text{,}\) the expression itself produces a boolean type, either true or false.
It is important to note that expressions cannot occur on their own. Rather they occur as part of the program’s statements. Here are some additional examples of expressions:
num = 7 // An assignment expression of type int
num = square(7) // An method call expression of type int
num == 7 // An equality expression of type boolean
The first of these is an assignment expression. It has a value of 7, because it is assigning 7 to num. The second example is also an assignment expression, but this one has a method call, square(7), on its right hand side. (We can assume that a method named square() has been appropriately defined in the program.) A method call is just another kind of expression. In this case, it has the value 49. Note that an assignment expression can be turned into a stand-alone assignment statement by placing a semicolon after it.
The third expression is an equality expression, which has the value true, assuming that the variable on its left is storing the value 7. It is important to note the difference between the assignment operator (\(=\)) and the equality operator (\(==\)).
Principle1.5.14.Equality and Assignment.
Be careful not to confuse = and ==. The symbol = is the assignment operator. It assigns the value on its right-hand side to the variable on its left-hand side. The symbol == is the equality operator. It evaluates whether the expressions on its left- and right-hand sides have the same value and returns either true or false.
ExercisesSelf-Study Exercises
1.Fill-In, Assignment statements.
The variable num will have the value after the following two statements are executed:
int num = 11;
num = 23 - num;
2.Fill-In, Assignment statements.
Write a statement that will declare an int variable named num2 and assigns it an initial value of 0: .
Subsection1.5.8Class Definition
A Java program consists of one or more class definitions. In the HelloWorld example, we are defining the HelloWorld class, but there are also three predefined classes involved in the program. These are the Object,String, and System classes all of which are defined in the Java class library. Predefined classes, such as these, can be used in any program.
As the HelloWorld program’s comments indicate, a class definition has two parts: a class header and a class body. In general, a class header takes the following form, where the parts marked \(_{opt}\) are optional.
The purpose of the header is to give the class its name (HelloWorld), identify its accessibility (public as opposed to private), and describe where it fits into the Java class hierarchy (as an extension of the Object class).
In this case, the header begins with the optional access modifier, public, which declares that this class can be accessed by any other classes. The next part of the declaration identifies the name of the class, HelloWorld. And the last part declares that HelloWorld is a subclass of the Object class. We call this part of the definition the class’s pedigree.
As you recall from Chapter 0, the Object class is the top class of the entire Java hierarchy. By declaring that HelloWorld extends Object, we are saying that HelloWorld is a direct subclass of Object. In fact, it is not necessary to declare explicitly that HelloWorld extends Object because that is Java’s default assumption. That is, if you omit the extends clause in the class header, Java will automatically assume that the class is a subclass of Object.
The class’s body, which is enclosed within curly brackets, { and }, contains the declaration and definition of the elements that make up the objects of the class. This is where the object’s attributes and actions are defined.
Subsection1.5.9Declaring an Instance Variable
There are generally two kinds of elements declared and defined in the class body: variables and methods. As we described in Chapter 0, an instance variable is a variable that belongs to each object, or instance, of the class. That is, each instance of a class has its own copies of the class’s instance variables. The HelloWorld class has a single instance variable, (greeting), which is declared as follows:
private String greeting = "Hello, World!";
In general, an instance variable declaration has the following syntax, some parts of which are optional:
[Modifiers] Type VariableName [InitializerExpression]
In declaring the greeting variable, we use the optional access modifier, private, to declare that greeting can only be accessed in the HelloWorld class; it cannot be directly accessed by other objects.
The next part of the declaration is the variable’s type (String), which means that it can store a string object. The type is followed by the name of the variable (greeting), which can be used throughout the HelloWorld class. For example, notice that greeting is used on line 11 in a println() statement.
The last part of the declaration is an optional initializer expression. In this example, we use it to assign an initial value, “Hello, World!,” to the greeting variable.
Subsection1.5.10Defining an Instance Method
Recall that a method is a named section of code that can be called or invoked to carry out an action or operation. In a Java class, the methods correspond to the object’s behaviors or actions. The HelloWorld program has two method definitions: the greet() method and the main() method.
A method definition consists of two parts: the method header and the method body. In general, a method header takes the following form, including some parts which are optional:
As with a variable declaration, a method definition begins with optional modifiers. For example, the definition of the greet() method on line 9 uses the access modifier, public, to declare that this method can be accessed or referred to by other classes.
The next part of the method header is the method’s return type. This is the type of value, if any, that the method returns. Both of the methods in HelloWorld have a return type of void. This means that they don’t return anything. Void methods just execute the sequence of statements given in their bodies. We’ll see examples of methods that return values in the next chapter.
The method’s name follows the method’s return type. This is the name that is used when the method is called. For example, the greet() method is called on line 17.
Following the method’s name is the method’s parameter list. A parameter is a variable that temporarily stores data values that are being passed to the method when the method is called. Some methods, such as the greet() method, do not have parameters, because they are not passed any information. For an example of a method that does have parameters, see the Riddle() constructor, which contains parameters for the riddle’s question and answer (Listing 1.3.9).
The last part of method definition is its body, which contains a sequence of executable statements. An executable statement is a Java statement that takes some kind of action when the program is run. For example, the statement in the greet() method,
System.out.println(greeting); // Output statement
prints a greeting on the console.
Subsection1.5.11Java Application Programs
The HelloWorld program is an example of a Java application program, or a Java application, for short. An application program is a stand-alone program, “stand-alone” in the sense that it does not depend on any other program, like a Web browser, for its execution.
Every Java application program must contain a main() method, which is where the program begins execution when it is run. For a program that contains several classes, it is up to the programmer to decide which class should contain the main() method. We don’t have to worry about that decision for HelloWorld, because it contains just a single class.
Because of its unique role as the starting point for every Java application program, it is very important that the header for the main method be declared exactly as shown in the HelloWorld class:
public static void main(String args[])
It must be declared public so it can be accessed from outside the class that contains it. And it must be declared static. Static methods are associated with their class, not with the class’s objects or instances. Because of this, a static or class method can be called before the program has created any instances (or objects) of that class.
This is important for main()’s special role as the program’s starting point, because main() is called by the Java runtime system before the program has created any objects.
The main() method has a void return type, which means it does not return any kind of value.
Finally, notice that main()’s parameter list contains a declaration of some kind of String parameter named args. This is actually an array that can be used to pass string arguments to the program when it is started up. We won’t worry about this feature until our chapter on arrays.
Subsection1.5.12Creating and Using Objects
The body of the main() method is where the HelloWorld program creates its one and only object. When it is run the HelloWorld program simply prints “Hello World!” on the console. In order for this action happen, the program needs to call the greet() method.
However, because the greet() method is an instance method that belongs to a HelloWorld object, we first need to create a HelloWorld instance. This is what happens in the body of the main() method:
The first statement declares a variable of type HelloWorld, which is then assigned a HelloWorld object.
The second statement creates a HelloWorld object by invoking HelloWorld’s default constructor: HelloWorld(). A default constructor has the same name as the class and merely creates an object of that class. It is defined automatically by Java and looks like this:
public HelloWorld() { } // Default constructor
Creating an object is called object instantiation because you are creating an instance of the object. Once a HelloWorld instance is created, we can use one of its instance methods to perform some task or operation.
Thus, in the third statement, we call the greet() method, which will print “Hello World!” on the console.
The HelloWorld program (Listing 1.5.1)illustrates the idea that an object-oriented program is a collection of interacting objects. Although we create just a single HelloWorld object in the main() method, there are two other objects used in the program. One is the greeting object, the “Hello, World!” String. The other is the System.out object, which is a special Java system object used for printing.
Subsection1.5.13Java JFrames
Java can run a program in a JFrame so that the output and interaction occurs in a Window (or Frame). Listing 1.5.16 shows a Java program named HelloWorldCanvas. This program does more or less the same thing as the HelloWorld application— it displays the “Hello, World!” greeting. The difference is that it displays the greeting within a Window rather than directly on the console.
As in the case of the HelloWorld console application program, HelloWorldCanvas consists of a class definition. It contains a single method definition, the paint() method, which contains a single executable statement:
g.drawString("Hello, World!",10,10);
This statement displays the “Hello, World!” message directly in a Window. The drawString() method is one of the many drawing and painting methods defined in the Graphics class. Every Java Canvas comes with its own Graphics object, which is referred to here simply as g. Thus, we are using that object’s drawString() method to draw on the window. Don’t worry if this seems a bit mysterious now. We’ll explain it more fully when we take up graphics examples again.
Activity1.5.3.
Try the HelloWorldCanvas program below.
The HelloWorldCanvas class also contains some elements, such as the import statements, that we did not find in the HelloWorld application. We will now discuss those features.
Subsection1.5.14Java Library Packages
Recall that the HelloWorld program used two pre-defined classes, the String and the System classes. Both of these classes are basic language classes in Java. The HelloWorldCanvas program also uses pre-defined classes, such as JFrame and Graphics. However, these two classes are not part of Java’s basic language classes. To understand the difference between these classes, it will be necessary to talk briefly about how the Java class library is organized.
A package is a collection a inter-related classes in the Java class library. For example, the java.lang package contains classes, such as Object,String, and System, that are central to the Java language. Just about all Java programs use classes in this package. The java.awt package provides classes, such as Button,TextField, and Graphics, that are used in graphical user interfaces (GUIs). The java.net package provides classes used for networking tasks, and the java.io package provides classes used for input and output operations.
All Java classes belong to some package, including those that are programmer defined. To assign a class to a package, you would provide a package statement as the first statement in the file that contains the class definition. For example, the files containing the definitions of the classes in the java.lang package all begin with the following statement.
package java.lang;
If you omit package statement, as we do for the programs in this book, Java places such classes into an unnamed default package.
Thus, for any Java class, its full name includes the name of the package that contains it. For example, the full name for the System class is java.lang.System and the full name for the String class is java.lang.String. Similarly, the full name for the Graphics class is java.awt.Graphics. In short, the full name for a Java class takes the following form:
package.class
In other words, the full name of any class has its package name as a prefix.
Of all the packages in the Java library, only the classes in the java.lang package can be refererced by their shorthand names. This means that when a program uses a class from the java.lang package, it can refer to it simply by its class name. For example, in the HelloWorld program we referred directly to the String class rather than to java.lang.String.
Subsection1.5.15The import Statement
The import statement makes Java classes available to programs under their abbreviated names. Any public class in the Java class library is available to a program by its fully qualified name. Thus, if a program was using the Graphics class, it could always refer to it as java.awt.Graphics. However, being able to refer toGraphics by its shorthand name, makes the program a bit shorter and more readable.
The import statement doesn’t actually load classes into the program. It just makes their abbreviated names available. For example, the import statements in HelloWorldCanvas allow us to refer to the JFrame,Canvas, and Graphics classes by their abbreviated names (Listing 1.5.16).
The import statement takes two possible forms:
import package.class
import package.*
The first form allows a specific class to be known by its abbreviated name. The second form, which uses the asterisk as a wildcard character (’*’), allows all the classes in the specified package to be known by their short names. The import statements in HelloWorldCanvas are examples of the first form. The following example,
import java.lang.*;
allows all classes in the java.lang package to be referred to by their class names alone. In fact, this particular import statement is implicit in every Java program.
Subsection1.5.16Qualified Names in Java
In the previous subsections we have seen several examples of names in Java programs that used dot notation. A qualified name is a name that is separated into parts using Java’s dot notation. Examples include package names, such as java.awt, class names, such as javax.swing.JFrame, and even method names, such as helloworld.greet().
Just as in our natural language, the meaning of a name within a Java program depends on the context. For example, the expression helloworld.greet() refers to the greet() method, which belongs to the HelloWorld class. If we were using this expression from within that class, you wouldn’t need to qualify the name in this way. You could just refer to greet() and it would be clear from the context which method you meant.
This is no different than using someone’s first name ( “Kim” ) when there’s only one Kim around, but using a full name ( “Kim Smith” ) when the first name alone would be too vague or ambiguous.
Principle1.5.17.Library Class Names.
By convention, class names in Java begin with an uppercase letter. When referenced as part of a package, the class name is the last part of the name. For example, java.lang.System refers to the System class in the java.lang package.
Principle1.5.18.Dot Notation.
Names expressed in Java’s dot notation depend for their meaning on the context in which they are used. In qualified names— that is, names of the form X.Y.Z— the last item in the name (Z) is the referent — that is, the element being referred to. The items that precede it (X.Y.) are used to qualify or clarify the referent.
The fact that names are context dependent in this way certainly complicates the task of learning what’s what in a Java program. Part of learning to use Java’s built-in classes is learning where a particular object or method is defined. It is a syntax error if the Java compiler can’t find the object or method that you are referencing.
Principle1.5.19.DEBUGGING TIP: Not Found Error.
If Java cannot find the item you are referring to, it will report an “X not found” error, where X is the class, method, variable, or package being referred to.