A Crash Course From CPP To Java
A Crash Course From CPP To Java
A Crash Course
from C++ to Java
C H A P T E R T O P I C S
understand classes, member functions, and constructors, then you will find
that it is easy to make the switch to Java.
Greeter.java
1 public class Greeter
2 {
3 public Greeter(String aName)
4 {
5 name = aName;
6 }
7
8 public String sayHello()
9 {
10 return "Hello, " + name + "!";
11 }
12
13 private String name;
14 }
GreeterTest.java
1 public class GreeterTest
2 {
3 public static void main(String[] args)
4 {
5 Greeter worldGreeter = new Greeter("World");
6 String greeting = worldGreeter.sayHello();
7 System.out.println(greeting);
8 }
9 }
This class has a main method, which is required to start a Java application. The main
method is static, which means that it doesn’t operate on an object. After all, when the
application first starts, there aren’t any objects yet. It is the job of the main method to
construct the objects that are needed to run the program.
The args parameter of the main method holds the command line arguments. We will dis-
cuss it in the section on arrays.
You have already seen the first two statements inside the main method. They construct a
Greeter object, store it in an object variable, invoke the sayHello method and capture
the result in a string variable. The final statement uses the println method of the Sys-
tem.out object to print the message and a newline to the standard output stream.
To build and execute the program, put the Greeter class inside a file Greeter.java and
the GreeterTest class inside a separate file GreeterTest.java. The directions for compil-
ing and running the program depend on your development environment.
The Java Software Development Kit (SDK) from Sun Microsystems is a set of com-
mand-line programs for compiling, running, and documenting Java programs. Versions
for several platforms are available at http://java.sun.com/j2se. If you use the Java
SDK, then follow these instructions:
1. Create a new directory of your choice to hold the program files.
2. Use a text editor of your choice to prepare the files Greeter.java and
GreeterTest.java. Place them inside the directory you just created.
3. Open a shell window.
4. Use the cd command to change to the directory you just created
5. Run the compiler with the command
javac GreeterTest.java
If the Java compiler is not on the search path, then you need to use the full path
(such as /usr/local/j2sdk1.4/bin/javac or c:\j2sdk1.4\bin\javac) instead of
just javac. Note that the Greeter.java file is automatically compiled as well since
4 CHAPTER 1 A Crash Course from C++ to Java
the GreeterTest class requires the Greeter class. If any compilation errors are
reported, then make a note of the file and line numbers and fix them.
6. Have a look at the files in the current directory. Verify that the compiler has gen-
erated two class files, Greeter.class and GreeterTest.class.
7. Start the Java interpreter with the command
java GreeterTest
Now you will see a message “Hello, World!” in the shell window (see Figure 1).
F i g u re 1
The structure of this program is typical for a Java application. The program consists of a
collection of classes. One class has a main method. You run the program by launching the
Java interpreter with the name of the class whose main method contains the instructions
for starting the program activities.
The BlueJ development environment, developed at Monash University, lets you test
classes without having to write a new program for every test. BlueJ supplies an interactive
environment for constructing objects and invoking methods on the objects. You can
download BlueJ from http://www.bluej.org.
With BlueJ, you don’t need a GreeterTest class to test the Greeter class. Instead, just
follow these steps.
1. Select “Project -> New…” from the menu, point the file dialog to a directory of
your choice and type in the name of the subdirectory that should hold your
classes. This must be the name of a new directory. BlueJ will create it.
2. Click on the “New Class…” button and type in the Greeter class.
3. Click on the “Compile” button to compile the class. Click on the “Close” button.
4. The class is symbolized as a rectangle. Right-click on the class rectangle, and
select “new Greeter(aName)” to construct a new object. Call the object
1.2 Documentation Comments 5
worldGreeter and supply the constructor parameter "Hello" (including the quota-
tion marks).
5. The object appears in the object workbench. Right-click on the object rectangle
and select “String sayHello( )” to execute the sayHello method.
6. A dialog box appears to display the result (see Figure 2).
F i g u re 2
As you can see, BlueJ lets you think about objects and classes without fussing with pub-
lic static void main.
Method comments contain additional information. For each method parameter, you
supply a line that starts with @param, followed by the parameter name and a short expla-
nation. Supply a line that starts with @return, describing the return value. You omit the
@param tag for methods that have no parameters, and you omit the @return tag for meth-
ods whose return type is void.
Here is the Greeter class with documentation comments for the class and its public
interface.
/**
A class for producing simple greetings.
*/
class Greeter
{
/**
Constructs a Greeter object that can greet a person or entity.
@param aName the name of the person or entity who should
be addressed in the greetings.
*/
public Greeter(String aName)
{
name = aName;
}
/**
Greet with a “Hello” message.
@return a message containing “Hello” and the name of
the greeted person or entity.
*/
public String sayHello()
{
return "Hello, " + name + "!";
}
F i g u re 3
F i g u re 4
Finally, it is always a good idea to write the method comment first, before writing the
method code. This is an excellent test to see that you firmly understand what you need to
8 CHAPTER 1 A Crash Course from C++ to Java
program. If you can’t explain what a class or method does, you aren’t ready to implement
it.
Once you have written the documentation comments, invoke the javadoc utility.
1. Open a shell window.
2. Use the cd command to change to the directory you just created
3. Run the javadoc utility
javadoc *.java
If the SDK tools are not on the search path, then you need to use the full path
(such as /usr/local/j2sdk1.4/bin/javadoc or c:\j2sdk1.4\bin\javadoc) instead
of just javadoc.
The javadoc utility then produces one HTML file for each class (such as Greeter.html
and GreeterTest.html) as well as a file index.html and a number of other summary files.
The index.html file contains links to all classes.
The javadoc tool is wonderful because it does one thing right: it lets you put the docu-
mentation together with your code. That way, when you update your programs, you can see
immediately which documentation needs to be updated. Hopefully, you will then update
it right then and there. Afterwards, run javadoc again and get a set of nicely formatted
HTML pages with the updated comments.
INTERNET The DocCheck program reports any missing javadoc comments. Download it
from http://java.sun.com/j2se/javadoc/doccheck/.
The Java SDK contains the documentation for all classes in the Java library, also called
the application programming interface or API. Figure shows the documentation of the
String class. This documentation is directly extracted from the library source code. The
programmers who wrote the Java library documented every class and method and then
simply ran javadoc to extract the HTML documentation.
Download the SDK documentation from http://java.sun.com/j2se. Install the docu-
mentation into the same location as the Java SDK. Point your browser to the docs/api/
index.html file inside your Java SDK directory, and make a bookmark. Do it now! You
will need to access this information very frequently.
1.3 Primitive Types 9
F igure 5
Ta b l e 1
Note that long constants have a suffix L and float constants have a suffix F, such as
10000000000L or 3.1415927F.
Characters are encoded in Unicode, an uniform encoding scheme for characters in many
languages around the world. Character constants are enclosed in single quotes, such as
'a'. Several characters, such as a newline '\n', are represented as 2-character escape
sequences. Table 2 shows all permitted escape sequences. Arbitrary Unicode characters
are denoted by a \u, followed by four hexadecimal digits, enclosed in quotes. For exam-
ple, '\u2122' is the trademark symbol (TM).
\b backspace (\u0008)
\f form feed (\u000C)
\n newline (\u000A)
\r return (\u000D)
\t tab (\u0009)
\\ backslash
\' single quote
\" double quote
\un1n2n3n4 Unicode encoding
Ta b l e 2
INTERNET You can find the encodings of tens of thousands of letters in many alphabets at
http://www.unicode.org.
Conversions that don’t incur information loss (such as short to int or float to double)
are always legal. Values of type char can be converted to int. All integer types can be
converted to float or double, even if it means a loss of precision. All other conversions
require a cast such as
double x = 10.0 / 3.0; // sets x to 3.3333333333333335
int n = (int)x; // sets n to 3
float f = (float)x; // sets f to 3.3333333
It is not possible to convert between the boolean type and number types.
The Math class implements useful mathematical functions—see Table 3. The methods of
the Math class are static methods. That is, they do not operate on objects. (Recall that
numbers are not objects in Java.) For example, here is how you call the sqrt method:
1.4 Control Flow Statements 11
double y = Math.sqrt(x);
Since the method doesn’t operate on an object, you must supply the class name to tell the
compiler that the sqrt method is in the Math class. In Java, every method must belong to
some class.
Method Description
Ta b l e 3
Mathematical Methods
The while and do statements are used for loops. The body of a do loop is executed at least
once.
while (x < target)
{
x = x * a;
n++;
}
do
{
x = x * a;
n++;
}
while (x < target);
The for statement is used for loops that are controlled by a loop counter.
for (i = 1; i <= n; i++)
{
x = x * a;
sum = sum + x;
}
You can define a variable in a for loop. Its scope extends to the end of the loop.
int i = 1; i <= n; i++)
for (i
{
x = x * a;
sum = sum + x;
}
// i no longer defined here
worldGreeter = Greeter
F i g u re 6
An Object Reference
1.6 Parameter Passing 13
You can have multiple references to the same object. For example, after the assignment
Greeter anotherGreeter = worldGreeter;
the two object variables both share a single object (see Figure 7).
worldGreeter = Greeter
anotherGreeter=
F i g u re 7
A Shared Object
If theGreeter class has a method that allows modification of the object (such as a
setName method), and if that method is invoked on the object reference, then all shared
references access the modified object.
anotherGreeter.setName("Dave");
// now worldGreeter also refers to the changed object
The special reference null refers to no object. You can set an object variable to null:
worldGreeter = null;
You can test if an object reference is currently null:
if (worldGreeter == null) ...
If you invoke a method on a null reference, an exception is thrown. Unless you supply a
handler for the exception, the program terminates.
It can happen that an object has no references pointing to it, namely when all object vari-
ables that are referred to are filled with other values or have been recycled. In that case,
the object memory will be automatically reclaimed by the garbage collector. In Java, you
never need to manually recycle memory.
daveGreeter = Greeter
other=
F i g u re 8
While a method can change the state of an object that is passed as a parameter, it can
never update the contents of any variable. If you call
obj.f(var);
where var is a variable, then the contents of var is the same number, Boolean value, or
object location before and after the call. In other words, it is impossible to write a
method that sets the current value of var with to another primitive type value or object
location.
Consider yet another set of contrived methods:
/**
Tries to copy the length of this greeter’s name into an integer variable.
@param n the variable into which the method tries to copy the length
*/
public void setLength(int n)
{
// this assignment has no effect outside the method
n = name.length();
}
/**
Tries to set another Greeter object to a copy of this object.
@param other the Greeter object to initialize
*/
public void setGreeter(Greeter other)
{
// this assignment has no effect outside the method
other = new Greeter(name);
}
Let’s call these two methods:
1.7 Packages 15
int length = 0;
Greeter worldGreeter = new Greeter("World");
Greeter daveGreeter = new Greeter("Dave");
worldGreeter.setLength(length); // has no effect on the contents of length
worldGreeter.setGreeter(daveGreeter);
// has no effect on the contents of daveGreeter
Neither call has any effect. Changing the value of the parameter variable does not affect
the variable supplied in the method call. Thus, Java has no call by reference. Both primi-
tive types and object references are passed by value.
1.7 Packages
Java classes can be grouped into packages. Package names are dot-separated sequences of
identifiers, such as
java.util
javax.swing
com.sun.misc
edu.sjsu.cs.cs151.alice
To guarantee uniqueness of package names, Sun recommends that you start a package
name with a domain name in reverse (such as com.sun or edu.sjsu.cs), since domain
names are guaranteed to be unique. Then use some other mechanism within your organi-
zation to ensure that the remainder of the package name is unique as well.
You place a class inside a package by adding a package statement to the top of the source
file:
package edu.sjsu.cs.cs151.alice;
public class Greeter
{
...
}
Any class without a package statement is in the “default package” with no package name.
The full name of a class consists of the package name followed by the class name, such as
edu.cs.cs151.alice.Greeter. Examples from the Java library are java.util.ArrayList
and javax.swing.JOptionPane.
It is tedious to use these full names in your code. Use the import statement to use the
shorter class name instead. For example, after you place a statement
import java.util.ArrayList;
into your source file, then you can refer to the class simply as ArrayList. If you simulta-
neously use two classes with the same short name (such as java.util.Date and
java.sql.Date), then you are stuck—you must use the full name.
Large programs consist of many classes in multiple packages. The class files must be
located in subdirectories that match the package name. For example, the class file
Greeter.class for the class
edu.sjsu.cs.cs151.alice.Greeter
must be in a subdirectory
edu/sjsu/cs/cs151/alice
of the project’s base directory. The base directory is the directory that contains all package
directories as well as any classes that are contained in the default package (that is, the
package without a name).
F i g u re 9
There is no shame associated with acknowledging that your method might throw a
checked exception—it is just “truth in advertising”.
If a method can throw multiple exceptions, you list them all, separated by commas:
public void read(String filename)
throws IOException, ClassNotFoundException
Whoever calls this method is now put on notice that there is the possibility that the
checked exception in the throws clause may occur. Of course, those calling methods also
need to deal with these exceptions. Generally, the calling methods also add throws decla-
rations. When you carry this process out for the entire program, the main method ends
up being tagged as well:
public static void main(String[] args)
throws IOException, ClassNotFoundException
{
...
}
If an exception actually occurs, the main method is terminated, a stack trace is displayed,
and the program exits.
However, if you write a professional program, you do not want the program to terminate
whenever a user supplies an invalid file name. In that case, you want to catch the excep-
tion. Use the following syntax:
try
{
...
code that might throw an IOException
...
}
catch (IOException exception)
{
take corrective action
}
An appropriate corrective action might be to display an error message and to inform the
user that the attempt to read the file has failed.
In most programs, the lower-level methods simply propagate exceptions to their callers.
Some higher-level method, such as main or a part of the user interface, catches excep-
tions and informs the user.
Occasionally, you need to catch an exception in a place where you can’t take corrective
action. For now, simply print a stack trace and exit the program. For example,
try
{
...
code that might throw an IOException
...
}
catch (IOException exception)
{
1.9 Array Lists and Arrays 19
salaries =
F i g u re 1 0
An Array Reference
After an array has been constructed, you cannot change its length. If you want a larger
array, you have to construct a new array and move the elements from the old array to the
new array. That’s a tremendous hassle and most programmers use an ArrayList to store
objects.
You can obtain a two-dimensional array with a constructor call such as
int[][] table = new int[10][20];
Access the elements as table[row][column].
The args parameter of the main method is an array of strings, the strings specified in the
command line. args[0] is the first string after the class name. For example, if you invoke
a program as
java GreeterTest Mars
then args.length is 1 and args[0] is "Mars" and not "java" or "GreetingTest".
1.10 Strings 21
1.10 Strings
Java strings are sequences of Unicode characters. The charAt method yields the charac-
ters of a string. String positions start at 0.
String greeting = "Hello";
char ch = greeting.charAt(1); // sets ch to 'e'
Java strings are immutable. Once created, a string cannot be changed. Thus, there is no
setCharAt method. That sounds like a severe restriction, but in practice it isn’t. For
example, suppose you initialized greeting to "Hello". You can still change your mind:
greeting = "Goodbye";
The string object "Hello" hasn’t changed, but greeting now refers to a different string
object.
The length method yields the length of a string. For example, "Hello".length() is 5.
Note that the empty string "" of length 0 is different from null—a reference to no string
at all.
The substring method computes substrings of a string. You need to specify the positions
of the first character that you want to include in the substring and the first character that
you no longer want to include. For example, "Hello".substring(1, 3) is the string "el"
(see Figure 11). Note that the difference between the two positions equals the length of
the substring.
'H''e''l''l''o'
0 1 2 3 4
Fig u r e 11
Extracting a Substring
Since strings are objects, you need to use the equals method to compare whether two
strings have the same contents.
if (greeting.equals("Hello")) ... // OK
If you use the == operator, you only test whether two string references have the identical
location. For example, the following test fails:
if ("Hello".substring(1, 3) == "el") ... // NO
The substring is not at the same location as the constant string "el", even though it has
the same contents.
If the substrings of a string are separated by a delimiter such as commas or white space,
you can use the StringTokenizer class from the java.util package to enumerate the
substrings. For example,
String countries = "Germany,France,Italy";
StringTokenizer tokenizer = new StringTokenizer(countries, ",");
while (tokenizer.hasMoreTokens())
{
22 CHAPTER 1 A Crash Course from C++ to Java
If a string and an object are concatenated, then the object is converted by the toString
method. Every class inherits a default implementation of the toString method from the
Object superclass, and it is free to override it to return a more appropriate string. For
example, the toString method of the Date class in the java.util package returns a
string containing the date and time that is encapsulated in the Date object. Here is what
happens when you concatenate a string and a Date object:
// default Date constructor sets current date/time
Date now = new Date();
String greeting = "Hello, " + now;
// greeting is a string such as "Hello, Wed Jan 17 16:57:18 PST 2001"
Sometimes, you have a string that contains a number, for example the string "7". To con-
vert the string to its number value, use the Integer.parseInt and Double.parseDouble
methods. For example,
String input = "7";
n = Integer.parseInt(input); // sets n to 7
If the string doesn’t contain a number, or contains additional characters besides a num-
ber, a NumberFormatException is thrown.
F i g u re 1 2
An Input Dialog
Console input reads from the System.in object. However, unlike System.out, which was
ready-made for printing numbers and strings, System.in can only read bytes. Keyboard
input consists of characters. To get a reader for characters, you have to turn System.in
into an InputStreamReader object, like this:
InputStreamReader reader = new InputStreamReader(System.in);
An input stream reader can read characters, but it can’t read a whole string at a time.
That makes it pretty inconvenient—you wouldn’t want to piece together every input line
from its individual characters. To overcome this limitation, turn an input stream reader
into a BufferedReader object:
BufferedReader console = new BufferedReader(
new InputStreamReader(System.in));
Now you use the readLine method to read an input line, like this:
System.out.println("How old are you?");
String input = console.readLine();
int count = Integer.parseInt(input);
The readLine method may throw an IOException if there is an input error. When the
end of the input is reached, the readLine method returns null.
if (generator.nextBoolean())
return "Hello, " + name + "!";
else
return "Goodbye, " + name + "!";
}
It would be wasteful to supply each Greeter object with its own random number genera-
tor. To share one generator among all Greeter objects, declare the field as static:
public class Greeter
{
...
private static Random generator = new Random();
}
Shared variables such as this one are relatively rare. A more common use for the static
keyword is to define constants. For example, the Math class contains the following defini-
tions:
public class Math
{
...
public static final double E = 2.7182818284590452354;
public static final double PI = 3.14159265358979323846;
}
The keyword final denotes a constant value. After a final variable has been initialized,
you cannot change its value.
These constants are public. You refer to them as Math.PI and Math.E.
A static method is a method that does not operate on objects. You have already encoun-
tered static methods such as Math.sqrt. Another use for static methods are factory meth-
ods, methods that return an object, similar to a constructor. Here is a factory method for
the Greeter class that returns a greeter object with a random name:
public class Greeter
{
public static Greeter getRandomInstance()
{
if (generator.nextBoolean())
return new Greeter("World");
else
return new Greeter("Mars");
}
...
}
You invoke this method as Greeter.getRandomInstance(). Note that static methods can
access static fields but not instance fields—they don’t operate on an object.
Static fields and methods have their place, but they are quite rare in object-oriented pro-
grams. If your programs contain many static fields and methods, then this may mean that
you have missed an opportunity to discover sufficient classes to implement your program
in an object-oriented manner. Here is a bad example that shows how you can write very
poor non-object-oriented programs with static fields and methods:
1.13 Programming Style 25
It is very common to use get and set prefixes for methods that get or set a property of an
object, such as
public String getName()
public void setName(String aName)
However, a Boolean property has prefixes is and set, such as
public boolean isPolite()
public void setPolite(boolean b)
There are two common brace styles: The “Allmann” style in which braces line up, and the
compact but less clear “Kernighan and Ritchie” style. Here is the Greeter class, format-
ted in the “Kernighan and Ritchie” style.
public class Greeter {
public Greeter(String aName) {
name = aName;
}
You should put spaces around binary operators and after keywords, but not after method
names or casts.
Good Bad
x > y x>y
(int)x (int) x
You should not use magic numbers. Use named constants (final variables) instead. For
example, don’t use
h = 31 * h + val[off]; // Bad--what’s 31?
What is 31? The number of days in January? The position of the highest bit in an inte-
ger? No, it’s the hash multiplier.
Instead, declare a local constant in the method
final int HASH_MULTIPLIER = 31
or a static constant in the class (if it is used by more than one method)
private static final int HASH_MULTIPLIER = 31
and then use HASH_MULTIPLIER instead of 31.
Exercises
Exercise 1.1. Add a sayGoodbye method to the Greeter class and add a call to test the
method in the GreeterTest class (or test it in BlueJ).
Exercise 1.2. What happens when you run the Java interpreter on the Greeter class
instead of the GreeterTest class? Try it out and explain.
Exercise 1.3. Add comments to the GreeterTest class and the main method. Document
args as “unused”. Use javadoc to generate a file GreeterTest.html. Inspect the file in
your browser.
Exercise 1.4. Bookmark docs/api/index.html in your browser. Find the documentation
of the String class. How many methods does the String class have?
Exercise 1.5. Write a program that prints “Hello, San José”. Use a \u escape sequence to
denote the letter é.
Exercise 1.6. What is the Unicode character of the Greek letter “pi” (π)? For the Chinese
character “bu” ( )?
28 CHAPTER 1 A Crash Course from C++ to Java
Exercise 1.7. Run the javadoc utility on the Greeter class. What output do you get?
How does the output change when you remove some of the documentation comments?
Exercise 1.8. Download and install the DocCheck utility. What output do you get when
you remove some of the documentation comments of the Greeter class?
Exercise 1.9. Write a program that computes and prints the square root of 1000, rounded
to the nearest integer.
Exercise 1.10. Write a program that computes and prints the sum of integers from 1 to
100 and the sum of integers from 100 to 1000. Create an appropriate class Summer that
has no main method for this purpose. If you don’t use BlueJ, create a second class with a
main method to instantiate two objects of the Summerclass.
Exercise 1.11. Add a setName method to the Greeter class. Write a program with two
Greeter variables that refer to the same Greeter object. Invoke setName on one of the
references and sayHello on the other. Print the return value. Explain.
Exercise 1.12. Write a program that sets a Greeter variable to null and then calls say-
Hello on that variable. Explain the resulting output. What does the number behind the
file name mean?
Exercise 1.13. Write a test program that tests the three set methods of the example,
printing out the parameter variables before and after the method call.
Exercise 1.14. Write a method void swapNames(Greeter other) of the Greeter class that
swaps the names of this greeter and another.
Exercise 1.15. Write a program in which Greeter is in the package
edu.sjsu.cs.yourcourse.yourname and GreeterTest is in the default package. Into
which directories do you put the source files and the class files?
Exercise 1.16. What is wrong with the following code snippet?
ArrayList strings;
strings.add("France");
Exercise 1.17. Write a GreeterTest program that constructs Greeter objects for all com-
mand line arguments and prints out the results of calling sayHello. For example, if your
program is invoked as
java GreeterTest Mars Venus
then the program should print
Hello, Mars!
Hello, Venus!
Write a small sample program to find out, then explain the answers.
1.13 Programming Style 29
Exercise 1.19. Write a program that prints the sum of its command-line arguments
(assuming they are numbers). For example,
java Adder 3 2.5 -4.1
should print The sum is 1.4
Exercise 1.20. Write a GreeterTest program that asks the user “What is your name?”
and then prints out "Hello, username". Use an input dialog.
Exercise 1.21. Write a GreeterTest program that asks the user “What is your name?” and
then prints out "Hello, username". Use a buffered reader.
Exercise 1.22. Write a class that can generate random strings with characters in a given
set. For example,
RandomStringGenerator generator = new RandomStringGenerator();
generator.addRange('a', 'z');
generator.addRange('A', 'Z');
String s = generator.nextString(10);
// a random string consisting of ten lowercase
// or uppercase English characters