Appendix B: Review of Java Fundamentals
This appendix will briefly review the core Java concepts that you should be familiar with to understand the material presented in this book. This is not a complete introduction to Java programming, so if any of the topics are unfamiliar, you may want to consult a textbook or tutorial series on Java
to learn more about the corresponding material.
Data Types and Operators
Let’s begin by listing some of the basic, or
primitive
, data types available in Java:
int
: Integers (numbers with no decimal part)
float
: Decimal values
double
: Decimal values, stored with twice the precision of a float
char
: A single character (a letter, number, or symbol)
boolean
: The value true or false
Another commonly used data type is
String
, which represents text: a set of characters. Technically, this is not a primitive data type, but it can be initialized in a similar way.
Java also uses the common binary arithmetic
operators
: addition, subtraction, multiplication, division (or quotient, in the case of integers), and remainder, represented by the symbols
+
,
-
,
*
,
/
, and
%
, respectively. When used with two values of the same type, the result will also be of the same type. For example, the value of
5.0/2.0
is
2.5
, whereas the value of
5/2
is
2
. The results are different because in the first example the values have type
double
, and in the second example the values have type
int
.
When performing arithmetic involving two types of values, the values will be converted, or
cast
, to the more complex type. For instance,
5.0/2
yields a value of
2.5
. If desired, a numeric value of one type can be manually cast to another type by prefacing it with the name of the desired type in parentheses. For example,
(double)2
produces a value of
2.0
, whereas
(int)2.5
produces the value
2
. (When casting to an
int
, the value is always rounded down to the nearest integer value.)
Primitive variables can be declared and initialized with a single line of code, with the following syntax:
variableType variableName = initialValue;
Alternatively, these tasks can be carried out in separate statements:
variableType variableName;
variableName = initialValue;
In addition to using
=
to assign values to variables, Java provides
assignment operators
(for brevity), which modify the value of a variable by a constant amount. For example, the statement
x = x + 5
can be replaced with the statement
x += 5
. Each of the other arithmetic operations has a corresponding assignment operator:
-=
,
*=
,
/=
, and
%=
.
Numeric
values
can be compared with the conditional operators:
==
for equality,
!=
for inequality,
<
for less than,
<=
for less than or equal to,
>
for greater than, and
>=
for greater than or equal to. The result of a comparison is a Boolean value—
true
or
false
—and can be stored in a Boolean variable if desired. Boolean values can be combined with the Boolean operators:
&&
for “and,”
||
for “or,” and
!
for “not.”
An
array
is an object that contains a fixed number of values of the same type. The length of the array is set when the array is created. The values in an array can be initialized when it is created (and the size will be inferred). For example, the following creates an array that contains five characters:
char[] letters = { 'g' , 'a' , 'm' , 'e' , 's' } ;
Alternatively, an array can be created with only the length specified, shown here for an array that will contain ten integers (and the values can be set at a later time):
int[] values = new int[10];
The
items
in an array are accessed by their position, or index, which begins with the number
0
. For example, given the preceding array named
letters
, the expression
letters[0]
produces the value
'g'
,
letters[1]
produces
'a'
, and so forth, up to
letters[4]
, which produces
's'
. Note that the array has length 5, but the positions are numbered 0 through 4. (This is true in general; an array with length
n
will have indices numbered 0 through
n
– 1.) Note that once an array is created, its size cannot be changed; trying to store a value in an array at a nonexistent index value will result in an error when the program is running.
Control Structures
The statements within a Java program are typically run one after the other in sequence. Control structures can change the order of execution, either by running some statements only when certain conditions are met or by repeating a given set of statements.
Conditional Statements
An
if
statement is used to specify that a certain set of statements should be run only when a certain condition (or combination of conditions or a Boolean expression) evaluates to true. For example, the following code will add
100
to the variable
bonus
only if the value of
time
is greater than
60
; if the value of
time
is
not
greater than
60
, the code contained within the braces will not be executed.
if (time > 60)
{
bonus += 100;
}
Any number of statements may be contained within the braces. However, if only one statement is contained within the braces, the braces may be omitted, and the code will have the same results, as follows:
if (time > 60)
bonus += 100;
An
if-else
statement is used when you need to provide an alternative set of statements that will be executed when the associated condition evaluates to
false
. The following code builds on the previous example, adding the behavior that if the value of
time
is not greater than
60
, then the value of bonus will be incremented by
50
instead.
if (time > 60)
{
bonus += 100;
}
else
{
bonus += 50;
}
On occasion, you may want to test a variable for equality against a set of values and execute a different set of statements in each case. For example, consider the following code, which prints a message depending on whether the value of
itemCount
is equal to
0
,
1
,
2
, or anything else.
if (itemCount == 0)
System.out.print("You have no items.");
else if (itemCount == 1)
System.out.print("You have a single item.");
else if (itemCount == 2)
System.out.print("You have two items.");
else
System.out.print("You have many items!");
A
switch
statement
presents an alternative way to write this type of code (which is often easier to read). The following code features a
switch
statement that has exactly the same effect as the
if-else
statements presented previously. Each of the value comparisons in the
if-else
statements correspond to an occurrence of the
case
keyword within the
switch
code block, while the final
else
statement corresponds to the
default
keyword. After listing the set of statements to be executed for a given case, a
break
statement must be included (otherwise, the statements corresponding to the following cases will also be executed, regardless of whether the variable is equal to the value presented)
.
switch (itemCount)
{
case 0:
System.out.print("You have no items.");
break;
case 1:
System.out.print("You have a single item.");
break;
case 2:
System.out.print("You have two items.");
break;
default:
System.out.print("You have many items!");
}
Repetition Statements
The
while
statement is used to repeat a set of statements as long as a given condition is true. For example, the following code will continue to add
5
to the variable
score
and subtract
1
from the value of
stars
as long as the value of
stars
is greater than
0
:
while (stars > 0)
{
score += 5;
stars -= 1;
}
A
while
statement is particularly useful when a set of statements needs to be repeated an unknown number of times. You must be careful when using a
while
statement, however, because if the associated condition always remains true, then the statements will continue to execute forever!
The
for
statement
is used to repeat a set of statements a fixed number of times. In typical usage, a variable is set to an initial value, and as long as a condition involving the variable is true, a set of statements is executed. Afterward, the value of the variable is changed by a given amount, the condition is checked again, and so forth, until the given condition evaluates to false. The following example initially sets a variable
n
to
1
, and as long as
n
is less than
10
, adds
3
to
points
; the value of
n
is increased by
1
with each iteration of the loop. Note that the statement
n++
has the same effect as
n += 1
.
for (int n = 1; n < 10; n++)
{
points += 3;
}
For
loops are particularly useful in tasks involving arrays. As an example, the following code initializes an array named
numbers
to store five integers, and the
for
loop stores the value
10*n
at each position
n
in the array. Note that the loop variable is initialized to
0
(as this is the first index in an array), and the condition is that the variable is less than the length (that is, the size or the capacity) of the array. (You must use the less-than comparison in the condition, since the largest index in an array is always equal to the length of the array minus 1.)
int[] numbers = new int[5];
for (int index = 0; index < numbers.length; index++)
{
numbers[index] = 10 * index;
}
A
variation
on the syntax of the
for
statement, called the enhanced for statement, is convenient for accessing the values of an array. As a motivating example, consider the following code, which takes each of the values from an array called
grades
and adds them all to a variable called
total
:
for (int index = 0; index < grades.length; index++)
{
int num = grades[index];
total += num;
}
The exact same
result
can be achieved with less code using the following code, which automatically extracts the elements of an array (in order), and stores them into a variable before proceeding to the statements contained within the loop:
for (int num : grades)
{
total += num;
}
Methods
A
method
is a set of statements, grouped together, that can be called upon repeatedly to perform a task. Every method has an associated name, can take zero or more values as input, and may or may not return a value. Each method is contained within a structure called a
class
, which is covered in further detail later. The syntax for a method is presented here, and the various components are summarized immediately afterward:
modifer returnType methodName ( variableType variableName , ... )
{
// statements
}
modifier
is a keyword (such as
public
or
private
) that indicates where this method can be used in the program (see later in the appendix for more information).
returnType
indicates the type of data being returned and can be set to
void
if no data is returned by the method.
methodName
is the name of the method.
Within the parentheses, for each input that is to be provided, you must list the type of input (indicated by
variableType
) and the name by which it will be referred to in the statements that follow (indicated by
variableName
).
For example, the following public-access method called
average
takes two
float
values as input, calculates their average (which is also a
float
), and returns this value:
public float average(float x, float y)
{
return (x + y) / 2;
}
Methods
can be called upon in two ways, depending on how they are written. Some methods may be called from the class that contains them. For example, the
Math
class contains a method named
sqrt
that calculates the square root of a number; to use this method to calculate the square root of 4, you would write
Math.sqrt(4)
. Alternatively, some methods are called from a variable. As an example, every
String
variable contains a method named
charAt
that returns the character at a given position in the string. If you create a
String
named
word
that contains the text “
games,”
then
word.charAt(2)
returns the character
'm'
.
Objects and Classes
An
object
is a collection of related data and methods that operate on that data. A
class
is a set of code that is used as a prototype or a blueprint from which objects can be created. Some classes are automatically available in Java (such as the
String
,
Math
, and
System
classes). To use other classes in your program, you must indicate which of the many available classes should be loaded by using an
import
statement. For example, to be able to use the
Random
class in your program, which is part of the
java.util
package,
at the beginning of your program you must include this line:
To create an
object
from this class (also called an
instance
of the class), you use the
new
operator, followed by a special method of the class called the
constructor
. The name of the constructor method will always be identical to the name of the corresponding class, and it may require input values to initialize the data that belongs to the class. For example, to create an instance of the
Random
class, you would use the following code:
Random rand = new Random();
Following this, you could then use the methods of the variable
rand
, such as
nextInt
(which returns a randomly generated integer), as follows:
int secret = rand.nextInt();
The previously mentioned
String
class is special in that it may be initialized in the same way as a primitive type variable (like
int
or
float
), but it may also be initialized using the
new
operator (which requires the text to be stored as input):
String name = new String("Lee");
One of the most powerful features of Java (or any object-oriented programming language) is the ability to define your own classes. As an example, the following class, called
Fraction
, stores the data used in a fractional number: a numerator and a denominator (both integers). There is a constructor to set these values, a method to create a
String
representation
of the fraction, and a method to convert the fraction to a
float
value (by calculating the quotient).
class Fraction
{
int numerator;
int denominator;
// constructor
Fraction(int n, int d)
{
numerator = n;
denominator = d;
}
// creates a String representation
public String toString()
{
return (numerator + "/" + denominator);
}
// convert to a float value
public float convertToFloat()
{
return (float)numerator / denominator;
}
}
Next is a sample class that uses the
Fraction
class as defined previously. In particular, it contains a method named
main
that you will run, which creates and initializes a
Fraction
object and then uses its methods and prints their results to the screen. A technical aside: you must declare the
main
method as
static
in order to be able to run the method directly from the class (with the code
Sample.main()
) rather than from an instance of the
class
.
class Sample
{
public static void main()
{
Fraction frac = new Fraction(3,4);
String fracString = frac.toString();
float fracValue = frac.convertToFloat();
System.out.println( "The value of " + fracString + " is " + fracValue );
}
}
Sometimes, when you write a class, you’ll want to control access to data, either to restrict the possible set of values that can be assigned or to prevent another part of the program from accidentally changing the data (possibly due to a mistake in the code).
Access modifiers
are used in such situations; they can be included to specify whether other classes can use a particular field or method. The two most common modifiers are
public
, which indicates that any class can access the corresponding variable or method, and
private
, which indicates that it may be accessed only within the class in which it is defined. There is a less frequently used modifier,
protected
, which allows access within the defining class and any subclasses of (that is, those that extend) the defining class.
As a practical example of when access modifiers are useful, let’s return to our custom
Fraction
class. The denominator of a fraction should never be set equal to zero (because division by zero leads to contradictory mathematical results). You prevent this unwanted
behavior
by setting the class fields to
private
and rewriting the constructor (or any other relevant methods) to take action in this case, as demonstrated here:
private int numerator;
private int denominator;
// constructor
Fraction(int n, int d)
{
numerator = n;
if (d == 0)
{
System.err.println("Invalid denominator; changing value to 1.");
denominator = 1;
}
else
{
denominator = d;
}
}
// other methods remain the same as before
}
Summary
These topics—data types, operators, control structures, methods, and classes—are the foundations on which you will create your own programs. In real applications, your code will typically be much longer than the examples presented; your classes will no doubt contain multiple
import
statements, declare many variables of various types, and have an assortment of methods, each of which contains a significant number of statements. When working on your own projects, in addition to writing your own classes, your programs will probably use many predefined classes as well. For this reason, it is good to spend some time becoming familiar with the style and type of information that is presented in the Java documentation format, whether it be the official Java language reference
or the documentation for any Java libraries you include in your projects.