Chapter 2. Java Programming Essentials

Java is a mature programming language that offers many good features and capabilities that make it popular on many computer systems. Java is quite popular among Linux server programmers and administrators, as well as Windows application programmers. The key aspect of Java that makes it so appealing is its built-in library support. The C++ language cannot even begin to do what Java can do out of the box, so to speak. That is, you can’t do any graphics programming in C++ without an extra graphics library (such as OpenGL or Direct3D). Java, on the other hand, has everything built in (while still supporting add-on libraries). If you are just getting started as a Java programmer, then this chapter will help you gain some familiarity with the Java language. You will learn most of the basics in this chapter that you will need to write a game. There is a lot more to the Java language than what you will learn about in this sole chapter, obviously—many whole books have been written on Java programming. This chapter will help give you a jumpstart if you are new to Java. If you have experience with Java, you may find the information to be overly simple, but it is more important for a beginner to understand concepts rather than standards.

Here is what you will learn in this chapter:

  • Writing Java code using applets

  • How to use the Java data types

  • The basics of object-oriented programming

  • Writing Java classes

Java Applets and Applications

There are two different types of programs you can compile with Java: applications and applets. A Java application—the most common type of Java program—is a program compiled to run on a computer as a standalone application. A Java applet, on the other hand, is compiled specifically to run in a web browser. Java applications are usually written to run as server programs or just for one user, whereas applets run as client programs in a networked environment. For example, Java Web Server (JWS) is a Java application that hosts web page files to a web browser (such as Internet Explorer or Mozilla Firefox), and it is comparable to Microsoft’s Internet Information Server (IIS) web server and the open-source Apache web server. But, Java applications are not solely devoted to services, as we can use the Swing library and the Abstract Windowing Toolkit (AWT) to bring up a graphical window for an application with all the same features as an applet window. Since applications are much easier to use, requiring fewer steps to compile and run, this is the approach we are taking in this new edition. The final game of Galactic War in the last chapter will support both.

Web Server Technology Explained

The main difference is that Microsoft’s web server (IIS) and the Apache web server were written in C++, while JWS was written in Java. JWS can host regular HTML web pages and custom Java Server Pages (JSP), which are custom web server programs written in Java. A Java applet is different: An applet is a “client-side” program that runs entirely in the web browser, not on the web server. A JSP application literally runs on the web server and sends content to the web browser, whereas an applet runs only in the web browser. For this reason, we say that server programs run on the “back end,” and applets run on the “front end.”

An applet is like an HTML file that a web browser (like Firefox) downloads from the web server and then displays to the user. Microsoft’s IIS web server has gained in popularity and market share in recent years, thanks in part to the new .NET Framework, ASP.NET, and Web Services technologies. Active Server Pages .NET (ASP.NET) pages are similar to JSPs in concept, but ASP sites are written in Basic or C#, while JSP sites are built entirely with Java. If you don’t know much about web servers and web applications, don’t worry—we will only be writing web client programs, not server programs.

Hosting Java Applets

If you really find that you enjoy Java, then you may want to consider creating or enhancing your own website with Java applets. You can build an entire website as one large applet or you can embed many different applets inside a standard HTML page to enhance your website. One of the strong suits of Java is that you don’t need any special type of web server in order to use Java on your website. Java has been around since 1995, and web browsers have supported Java since Java 1.1. Microsoft Internet Explorer and Mozilla Firefox support the latest version of Java. To update your browser, simply install Java SE 6, and the installer will add a plug-in to your web browser automatically. This is necessary if you want to run the applet examples in this book.

Compiling Java Code

The easiest way to compile a Java program is by using the command-line compiler. As you may recall from Chapter 1, you use the javac.exe program to compile a .java file into a .class file. You then use the appletviewer.exe program in conjunction with an .html container file with an embedded applet tag to run your Java applet in the Applet Viewer program. You can also open this HTML test file in a web browser to run the applet. One of the main reasons why TextPad is such a useful editor is that it generates the HTML container file automatically when it invokes AppletViewer, which is a real time saver if you’re in a hurry.

We looked at NetBeans and Eclipse in the previous chapter. These are relatively large Integrated Development Environments (IDEs) for building software projects. For simple games, I recommend using a text editor like TextPad and the command-line tools. But one really great feature of both NetBeans and Eclipse is syntax lookup, which lists the contents of classes and parameters for functions, effectively eliminating the need for a manual! This is one feature you won’t get with a text editor, and so I recommend using one of these IDEs for larger game projects.

The Java Language

There are many built-in classes in Java, but we will only be using a few of them to build games. Now then, I suppose even a word like “class” might be a mystery if you are new to programming. A class is a sort of container that holds both data and functions. Do you have any experience with the C++ language? Java was based on C++ by “borrowing” all of the best features of C++ and dropping the more difficult aspects of the language. The programmers who developed the Java specification created a language that is more of an evolution than something created. C++ is a powerful language used to build everything from cell phone games to operating systems to supercomputer simulations. Linux was built with C++. Microsoft Windows was built with C++. The Java Development Kit was built with C++! The power of C++ makes it difficult for beginners to grasp, and even professionals who have spent many years working with databases and web applications may be stymied when confronted with a mysterious C++ error message. It is a world-class language, and there are dozens of compilers for it on every computer system, but it is very difficult to master. Here is a list of software built with the C++ language:

  • Microsoft Windows

  • Microsoft Office

  • Microsoft Visual Studio

  • NVIDIA video card drivers

  • Mozilla Firefox

  • Linux core

  • Mac OS X

  • Apple iOS (iPod, etc.)

  • OpenOffice

I could go on and on, listing thousands of operating systems, productivity applications, video card device drivers, compilers, assemblers, interpreters, and so on, that were built with C++.

Now consider Java. There is just one compiler for it, the Java Development Kit (JDK), which is available for most computer systems. Java is innovative enough to be called a new language, but it was heavily influenced by C++. Java is much easier to program than C++. Java automatically handles memory management for you—all you do is allocate memory for new variables and objects, and then you don’t really need to worry about freeing up the memory afterward. Java uses a technology called garbage collection to remove unused things from memory that your program no longer needs. To give you an analogy, in the realm of Java, you don’t even need to carry the trashcan out to the street for pickup because the garbage collector just picks up all the trash thrown about in your house. The garbage collector is sort of like a little robot that scurries about the house searching for trash to pick up. When you are done with your Chinese takeout, just pitch the container and your napkin, and the little trash robot will find it and clean it up for you.

This could lead to sloppy programming habits if you spend many years programming in Java and then switch to a more demanding language like C++, so Java makes it possible for you to write solid code that cleans up after itself if you wish to use it. There is a drawback to garbage collection, though: You can’t tell it specifically when to pick up the trash (variables and objects that are no longer used), only that there is trash to be picked up (as with the real-world garbage collectors most of the time!).

Java Data Types

Let’s now learn about the basic data types available in Java, because you will be using these data types throughout the book (and presumably for the rest of your programming career).

Integer Numbers

Java supports many data types, but probably the most basic data type is the integer. Integers represent whole numbers, which are numbers that have no decimal point. There are several types of integer that you may use depending on the size of number you need to store. Table 2.1 shows the types of integers you can use and their attributes.

Since Java programs can run on a wide variety of computer systems (this is called cross-platform support), you might be wondering whether these data type values will be the same on every system. After all, a Java program can run on a little cell phone or it can run on a supercomputer, such as a Cray Red Storm system.

Table 2.1. Integer Data Types

Type

Size in Bits

Range

byte

8 bits

–128 to 127

short

16 bits

–32,768 to 32,767

int

32 bits

–2,147,483,648 to 2,147,483,647

long

64 bits

–9,223,372,036,854,775,808 to 9,223,372,036,854,775,807

Tip

For more information about supercomputers, check out www.top500.org for a list of the top 500 supercomputers in the world. At the time of this writing, the most powerful computer is Oak Ridge National Laboratory’s 224,162-core Jaguar, based on a Cray XT5-HE, which achieves a peak of 2,331,000 GFlops. Four years ago, when the second edition of this book was published, the top supercomputer was IBM’s BlueGene/L at 280,000 GFlops—a nearly ten-fold increase.

Java gets around the data type inconsistency in C++ by defining that data types will be exactly the same, regardless of the computer system on which the Java program is running. It’s the job of the Java Runtime Environment (JRE) to determine at runtime how the current computer system will handle the data types your Java program is trying to use, and it does this seamlessly behind the scenes.

Definition

FLOPS is an acronym that stands for FLoating point OPerations per Second, used to measure computer performance.

Floating-Point Numbers

There are two data types available in Java for working with floating-point numbers. A floating-point represents a decimal value. The float data type stores a 32-bit single-precision number. The double data type stores a 64-bit double-precision number. Table 2.2 shows the specifics of these two data types.

Table 2.2. Floating-Point Data Types

Type

Size in Bits

Range

float

32 bits

1.4E-45 to 3.4028235E+38

double

64 bits

4.9E-324 to 1.7976931348623157E+308

The easiest way to determine the range for a numeric data type is to use the MIN_VALUE and MAX_VALUE properties of the base data type classes. Although we use lowercase to specify the type of a numeric variable (byte, short, int, long, float, and double), these base numeric types are actually instances of Java classes (Byte, Short, Integer, Long, Float, and Double). Therefore, we can take a peek inside these base classes to find some goodies. The MIN_VALUE and MAX_VALUE properties will give you the range of values for a particular data type.

I have written a program called DataTypes that displays these values in an applet window. The output is shown in Figure 2.1, and the source code listing follows. This program is on the companion website (www.courseptr.com/downloads) in the sourceschapter02DataTypes folder.

The DataTypes program displays the range for each numeric data type.

Figure 2.1. The DataTypes program displays the range for each numeric data type.

import java.awt.*;
import javax.swing.*;
public class DataTypes extends JFrame {
    public DataTypes() {
        super("DataTypes");
        setSize(600,400);
        setVisible(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
    public void paint(Graphics g) {
        g.setFont(new Font("Courier New", Font.PLAIN, 16));
        g.drawString("Byte : " +
            Byte.MIN_VALUE + " to " + Byte.MAX_VALUE, 20, 50);
        g.drawString("Short : " +
            Short.MIN_VALUE + " to " + Short.MAX_VALUE, 20, 70);
        g.drawString("Int : " +
            Integer.MIN_VALUE + " to " + Integer.MAX_VALUE, 20, 90);
        g.drawString("Long : " +
            Long.MIN_VALUE + " to " + Long.MAX_VALUE, 20, 110);
        g.drawString("Float : " +
            Float.MIN_VALUE + " to " + Float.MAX_VALUE, 20, 130);
        g.drawString("Double : " +
            Double.MIN_VALUE + " to " + Double.MAX_VALUE, 20, 150);
    }
    public static void main(String[] args) {
        new DataTypes();
    }
}

Characters and Strings

There are two data types in Java for working with character data: char and String. Note that char is a base data type, while String is automatically recognizable as a class (due to the uppercase first letter). Java tries to make programming easy for C++ programmers by using many of the same basic data types in order to make it easier to convert C and C++ programs to Java. So we have a base char and a String class; of course, as you now know, every data type in Java is a class already.

You define a char variable like this:

char studentgrade;
char examscore = 'A';

The char data type can only handle a single character, not an entire string. Note that a character is identified with single quotes (’A’) rather than double quotes, necessary for strings. The String data type (or rather, class) is very easy to use and is used by many of the Java library methods. (Remember, a method is a function.) For instance, you have seen a lot of the Graphics class so far in this chapter because it is the main way to display things (such as text) in an applet window. Here are a couple of different ways to create a string:

String favoritegame = "Sid Meier's Civilization V"
String username;
username = "John" + " R. " + "Doe";

In addition to supporting the plus operator for combining strings (something that C programmers look upon with envy), the String class also comes equipped with numerous support methods for manipulating strings. I won’t go over every property and method in the String class here because that is the role of a Java reference book—to cover every single detail.

Tip

If you are enjoying Java so far and you think you will stick with it, you will definitely need a comprehensive Java language reference book. I recommend Herbert Schildt’s Java: The Complete Reference, 7th Edition (McGraw-Hill Osborne Media, 2006). A good introductory book for beginners is John Flynt’s Java Programming for the Absolute Beginner, Second Edition (Cengage, 2006). If you want just a good online reference, the online docs for Java can be found at http://java.sun.com/reference/api/.

One good example of a function we’ve been using in this chapter is Graphics .drawString(). This function has many overloaded versions available (overloading is explained later in this chapter, in the section entitled “Object-Oriented Programming”) that give you a lot of options for printing text to the applet window, but the main version I use is this:

drawString(String str, int x, int y)

Table 2.3. String Class Methods

Method

Description

contains

Returns true if one string is contained in another string

endsWith

Returns true if the string ends with a certain string

equalsIgnoreCase

Compares strings without considering uppercase or lowercase

length

Returns the length of the string

replace

Replaces all occurrences of a sub-string with another sub-string in a string

trim

Removes blank spaces from the start and end of a string

Note

We have just scratched the surface of Java 2D (with the Graphics and Graphics2D classes). This will be the focus of most of Part II, covering Chapters 4 through 10. You will learn about class inheritance later in this chapter.

Table 2.3 lists just some of the useful methods in the String class. This is by no means a complete list.

If you want to see all of the properties and methods in a class (such as String), the easiest way to get a list, aside from using a reference book, is to create an instance of a class (such as String s) and then use the dot operator (.) to cause NetBeans or Eclipse to bring up the contents of the class. This built-in “look” feature works with the Java language classes as well as classes you have written yourself, as shown in Figure 2.2.

NetBeans displays the contents of a class with a pop-up window.

Figure 2.2. NetBeans displays the contents of a class with a pop-up window.

Possibly the single-most beneficial advantage to using an IDE is the built-in help system, which is available in tools such as NetBeans. If you aren’t using an IDE that provides context-sensitive help and class member lists, then you will need a good reference book or website.

Tip

If you are looking for help on a specific Java language term or class, the easiest way to look up that information is by using Google. Search “java keyword” to quickly locate the reference. For example, the first Google result for “java graphics2d” will most likely be a URL to one of Sun’s own Java reference pages. Or you can just go straight to the source and search through the class listings at http://java.sun.com/reference/api/. Looking up the reference instead of using the editor’s pop-up help may not be as convenient, but it will make you a stronger programmer.

Booleans

The Boolean data type can be set to either true or false, and it is useful as a return value for methods. For instance, in some of the example programs you’ve seen so far, there have been methods that returned a Boolean based on whether the code succeeded. You can declare a boolean variable like so:

boolean gameover = false;

Here is a short method that returns a Boolean value based on whether a value is within a boundary of a minimum and maximum value:

   public boolean checkBounds(long val, long lower, long upper) {
         if (val < lower || val > upper)
           return false;
       else
           return true;
   }

Here is an example of using the checkBounds method to determine whether a sprite’s position on the screen (in the horizontal orientation) is within the screen’s boundary:

spriteX = spriteX + 1;
if (checkBounds(spriteX, 0, 639) == true)
    spriteX = 0;

This short example assumes that the spriteX variable has already been declared earlier in the program. The sprite’s X position on the screen will wrap around to the left edge anytime the sprite moves off the right edge of the screen. This Boolean method can also be written like this, where the == true is assumed in the if statement:

if (checkBounds(spriteX, 0, 639)) ...

Note that I have left out the == true in this line of code. This is possible because Java evaluates the return value of the checkBounds method and replaces the method call with the return value when the program is running. Thus, if the checkBounds method returns true, the if statement becomes this:

if (true) . . .

This is why we can leave the == true out of the equation. Conversely, when you want to test for a false return value, you can insert == false in the if statement or you can use the logical negative operator (!) in the statement:

if (!checkBounds(spriteX, 0, 639)) ...

The result is that if checkBounds returns false, the if statement will execute the code that follows; otherwise, the code is not executed. Speaking of which, you may include a single line of code after an if statement, or you may include a code block enclosed in curly braces as follows. This is especially helpful if you want to do more than one thing after a conditional statement returns true or false:

   public boolean checkBounds(long val, long lower, long upper) {
         if (val < lower || val > upper) {
   
                       . . .
                   return false;
              } else {
   
                  . . .
                  return true;
              }
     }

The use of curly braces in this new version of checkBounds might not change anything, but it does allow you to add more lines of code before each of the return statements. (For instance, you may want to display a message on the screen before returning.)

Arrays

An array is a collection of variables of a specific data type that are organized in a manageable container. An array is created using one of the base data types, a Java library class, or one of your own classes. To tell Java that you want an array, attach brackets to the data type in your variable declaration:

int[] highScoreList;

But there are two steps to creating an array because an array must first be defined, and then memory must be allocated for it. First, you define the data type and array variable name, then you allocate the array by specifying the number of elements in the array with the new operator:

int[] studentGrades;
studentGrades = new int[30];

Note that I have allocated enough memory for this array to hold 30 elements in the studentGrades array. You can also define a new array with a single line of code:

int[] studentGrades = new int[30];

I don’t know about you, but I enjoy writing beautiful code like this. I get a chill when writing code like this because my imagination starts to take off with visions of scrolling backgrounds and spaceships and bullets and explosions, all of which are made possible with arrays. But the real power of an array is made obvious when you start iterating through an array with a loop. If you need to update the values of this array, you might access the array elements individually like this:

studentGrades[0] = 90;
. . .
studentGrades[29] = 100;

If you truly need to set each element in an array individually, then an array can still help to cut down on the clutter in your program. And an array will always benefit from processing in a loop when it comes to things such as printing out the contents of the array or storing it in a data file, or for any other purpose you may have for the array. Let’s set all of the elements in an array to a starting value of zero (this is good programming practice):

long[] speed = new long[100];
for (int i = 0; i < 100; i++) {
    speed[i] = 0;
}

There is another way to create an array by setting the initial values of the array right at the definition. This array of five floats is defined and initialized in memory with starting values at the same time.

float[] radioStations = { 88.5, 91.3, 97.7, 101.5, 103.0 };

You can also create multidimensional arrays. An array with more than one dimension will have a multiplicative number of elements (based on the number of elements in each dimension) because for every one element in the first dimension, there are N elements in the next dimension (based on the size of the next dimension). In my own experience writing games, I seldom use more than one dimension for an array because it is possible (and more efficient) to use a single-dimensioned array, and then index into it creatively to deal with multiple dimensions.

Here is an example two-dimensional array that stores the values for a game level. The pound characters (#) represent walls (or any other object you want in your game) while the periods (.) represent dirt, grass, or any other type of image. I presume that this is a level for a tile-based game, where each character in the array is drawn to the screen as a tile from a bitmap file.

char[][] gameLevel = {
    {'#','#','#','#','#','#','#','#','#','#'},
    {'#','.','.','.','.','.','.','.','.','#'},
    {'#','.','.','.','.','.','.','.','.','#'},
    {'#','.','.','.','.','.','.','.','.','#'},
    {'#','.','.','.','.','.','.','.','.','#'},
    {'#','.','.','.','.','.','.','.','.','#'},
    {'#','#','#','#','#','#','#','#','#','#'}
};

Another common practice is to create a game level with just numbers (such as 0 to 9). Some programmers prefer to use character-based levels because they sort of look more like a game level, and are, therefore, easier to edit. I tend to prefer integer-based game levels using a level editor such as Mappy, which exports levels as a comma-delimited array of numbers. Here is how Mappy might export the same level with numeric data:

2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 1, 1, 1, 1, 1, 1, 1, 1, 2,
2, 1, 1, 1, 1, 1, 1, 1, 1, 2,
2, 1, 1, 1, 1, 1, 1, 1, 1, 2,
2, 1, 1, 1, 1, 1, 1, 1, 1, 2,
2, 1, 1, 1, 1, 1, 1, 1, 1, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2

Tip

You can download Mappy from www.tilemap.co.uk. The subject of tiled scrolling is not covered in this book. For an exhaustive guide to the subject, I refer you to Visual Basic Game Programming for Teens, 3rd Edition (Course PTR, 2010) (or the sister book Visual C# Game Programming for Teens). Although this book covers Basic, it is one of the few books that explains how to build a level editor from scratch, and the concepts can be applied to Java should you wish to create such a game.

Can you make out the similarity between the two game levels shown here? It’s all the same data, just represented differently. When Mappy exports a level like this, it sends the data to a text file that you can then open and paste into your game’s source code. To make it work, you would define an array to handle the data like this:

int[][] gameLevel = {
    {2, 2, 2, 2, 2, 2, 2, 2, 2, 2},
    {2, 1, 1, 1, 1, 1, 1, 1, 1, 2},
    {2, 1, 1, 1, 1, 1, 1, 1, 1, 2},
    {2, 1, 1, 1, 1, 1, 1, 1, 1, 2},
    {2, 1, 1, 1, 1, 1, 1, 1, 1, 2},
    {2, 1, 1, 1, 1, 1, 1, 1, 1, 2},
    {2, 2, 2, 2, 2, 2, 2, 2, 2, 2}
};

Tip

Don’t forget the semicolon at the end of an array declaration, or you will get some very strange errors from the Java compiler.

I prefer to treat a game level (or other array-based data sequence) as a single-dimensioned array because data like this is easier to work with as a one-dimensional array. Here is how I would define it:

int[] gameLevel = {
    2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
    2, 1, 1, 1, 1, 1, 1, 1, 1, 2,
    2, 1, 1, 1, 1, 1, 1, 1, 1, 2,
    2, 1, 1, 1, 1, 1, 1, 1, 1, 2,
    2, 1, 1, 1, 1, 1, 1, 1, 1, 2,
    2, 1, 1, 1, 1, 1, 1, 1, 1, 2,
    2, 2, 2, 2, 2, 2, 2, 2, 2, 2
};

Do you see the subtle difference between this 1D array and the 2D array defined before? All I need to know are the width and height of the array data, and then I don’t need multiple dimensions. In this example, this game level is 10 tiles wide and 10 tiles deep, for a total of 100 tiles. (A tile is a small bitmap used to build a game world in a 2D scrolling game, and it very closely resembles the analogy of floor tiles in the way it is used.)

The Essence of Class

In case you haven’t noticed, I’ve been talking about classes a lot. That’s because you can’t really get around the subject when writing a Java program. The main part of a Java source code file itself is a class. You might have seen a C program before and you might already be familiar with the main() function. Here is a simple C program:

int main(int argc, char argv[]) {
    printf("I am a C program.
");
    return 0;
}

Let’s take a look at the same program written in pure C++:

#include < iostream >
int main(int argc, char argv[]) {
    std::cout << "I am a C++ program." << std::endl;
    return 1;
}

Now take a look at the same program written in Java:

import java.io.*;
public class SampleJava {
    public static void main(String args[]) {
        System.out.println("I am a Java program.");
    }
}

Do you see any similarities among these programs? You should, because they are listed in evolutionary order. Now, I don’t want to get into an argument with anyone about whether Java is truly an evolutionary leap ahead of C++ because I’m not sure if I believe that in the strictest sense (with a feature comparison). But I do like to think of Java as the next logical step above C++; it is easier, less prone to error, but not as powerful. Doesn’t that describe any system that tends to evolve over time? Take the computer industry itself, for instance. The earliest computers were built with thousands of vacuum tubes, which were difficult to maintain and very prone to error; and as far as power consumption goes, I think the computers of old were definitely more powerful than the computers we commonly use today—but let’s not talk about performance, which is no contest.

The C program is quite simple and maybe even readable by a non-programmer (who may not understand anything other than the printf line, and even then with much confusion). The C++ program is so much gobbledygook to anyone but a programmer. But those of us with a C++ background often describe C++ code as beautiful and elegant, with a powerful, perhaps even intimidating, lure. The Java program is very similar to the C and C++ programs. Like the C++ program, the Java program must “get something” from “somewhere else” in the form of the import java.io.* statement. This java.io is a library that provides access to the System.out class, which is used for printing out text (as you probably guessed). But the biggest difference is that the Java program is located inside a class. This class is called SampleJava, and inside this class (enclosed with curly braces) is a main function very similar to the main functions found in the C and C++ programs.

What is this SampleJava class, you may ask? The truth is, everything in Java is a class, and it is not possible to do anything useful in Java without using a class. All source code that you write in Java will be enclosed inside a class definition.

The main Function

The core of a Java application is the main function. (Note that applets typically don’t have a main function, as I’ll explain shortly.) The main function has this basic format:

public static void main(String args[]) { }

The parameter (String args[]) allows you to pass information to the Java program and is only practical when developing a Java application (rather than an applet) to which you can pass parameters, presumably from a command prompt or shell. You can pass parameters to a Java applet, but that is not done very often. I once worked for a company that built vehicle tracking systems using GPS (global positioning system), and my job was to maintain the Java program that displayed a map with all the vehicles in the state of Arizona moving along their routes. This Java program received vehicle tracking information from a server, and then displayed it in an applet.

Caution

Java applets don’t need a main function because there are several events that are found in an applet instead (such as init and paint).

Let’s dissect the main function to help you better understand what it does. The term public specifies that this function is visible outside the class. (Remember, every Java program runs inside a class.) The static term specifies that the function definition never changes and is not to be inherited (borrowed for use in another function). The static keyword is optional and not often used in an applet. The void term means that the function does not return a value. Every Java application you write will have a main function, just like every C and C++ program. However, a Java applet, which runs in a web browser, contains events instead and is not in complete control in the same way that a standalone Java application (with a main method) is.

However, you can write Java classes that don’t have a main function. Why would you want to do that? A class is usually created to perform a specific task, such as the handling of sprites in a game. You might write a sprite class that knows how to load a bitmap file and draw a sprite on the screen; then the main Java program (with the main function) will consume or use the sprite class, which itself has no main function. A class has its own variables and functions, some of which are hidden inside the class itself and invisible outside the class. What I’m describing here are some of the key aspects of object-oriented programming, or OOP. In some cases, as when developing an applet, you may just use the paint event rather than using a main function. (More on that later.)

Object-Oriented Programming

There are four main concepts involved in OOP, though you may not use all of them in every class you write:

  • Data hiding

  • Encapsulation

  • Inheritance

  • Polymorphism

I’ll briefly talk about each of these concepts because you will be dealing with these throughout the book. I don’t spend a lot of time discussing advanced concepts like these while writing Java games, and this book is not intended as a primer on the Java language. Hundreds of books have been written about Java programming, including some very complex textbooks on the subject used in college courses.

Data Hiding

Data hiding is a key concept of OOP because it provides a way to protect data within an object at runtime from direct manipulation. Instead of providing access to certain pieces of data, a class definition will include functions (often called methods or accessors/mutators in OOP lore) for retrieving and changing data (often called properties) that is hidden within the class definition. An accessor function retrieves a hidden variable; a mutator changes a hidden variable.

This way, the programmer can specify exactly what changes can be made to a private variable through the built-in mutator functions and return custom-formatted data through the accessor functions. For instance, if you want to make sure that a birth date is valid, the mutator function can restrict changes to a certain range (such as 0 to 120). The following source code demonstrates the concept of data hiding. I have intentionally kept the code listing simpler by not including any comments.

public class vehicle {
    private String make;
    private int numwheels;

    public String getMake() {
        return make;
    }
    public boolean setMake(String newmake) {
        if (newmake.length() > 0) {
            make = newmake;
            return true;
        } else {
            return false;
        }
    }

    public int getNumWheels() {
        return numwheels;
    }
    public boolean setNumWheels(int count) {
        if (count > 0 && count < 20)
        {
            numwheels = count;
            return true;
        } else {
            return false;
        }
    }
}

Encapsulation

Encapsulation is related to data hiding in that it describes how information and processes are both handled internally by a class. These two concepts are often used interchangeably, depending on the opinion of the programmer. (I prefer to use the term encapsulation rather than data hiding.) I would suggest that encapsulation involves modeling a real-world entity, whereas data hiding describes the ability to use private variables in a class. It’s common to encapsulate a real-world entity by writing a class that describes the data and functions for working with that data. In the vehicle class example, I have encapsulated the specifications for a basic vehicle inside a class with hidden (or private) data members and public functions (or methods).

Inheritance

Inheritance describes the ability to reuse class definitions and to make changes to a subclass that relies on a base class. For instance, the vehicle class might be used as a basis for many subclasses covering a wide range of vehicles, from two-wheel motorcycles to 18-wheel semi trucks. When you are writing the code for a class, it is best to put each class inside its own source code file. Java allows you to inherit from a single base class.

Note

Although C++ allows you to inherit from multiple base classes, this feature often causes more problems than it solves, so it is seldom used. Instead of multiple inheritance, Java allows you to use multiple interfaces—which are guidelines for the properties and methods that should be found within a particular class.

For instance, the SimpleClass program includes the source code listing for the vehicle class, and it is stored in a file called vehicle.java. Also included in the SimpleClass project is the main source code file called SimpleClass.java—and this file “consumes” or uses the vehicle class defined in the vehicle.java file. Additional classes can be written and saved in their own source files.

Tip

To add a new class to your project, just create a new text file with a .java extension and compile it separately from your main program file. This is very easy to do using TextPad by pressing Ctrl+1 to compile your Java code.

A constructor is a method that is called whenever you create a new class in your program. I’m not talking about typing in a new class, but when a class is instantiated into an object at runtime. When a new class is created (with the new operator), the class definition is used to construct an object. See where the keyword comes in here? The new object is “constructed” when it is being created at runtime; the class is a blueprint used to build or construct the object at runtime.

Definition

Instantiate means to create or to construct. Within the context of object-oriented programming, new objects are instantiated when they are created at runtime from the blueprint specified in a class definition (such as the vehicle class).

When I click the OK button on the Class Wizard dialog box, a new file called truck.java is added to my project, and it contains this source code:

public class truck extends vehicle {
    public truck() {
    }
}

This is a nice, clean starting point for a new class. Note that this class inherits from the vehicle class (extends vehicle), and it includes a simple constructor (public truck()). This constructor is called whenever you use new to create a new truck object, using code like this:

trucksilverado = new truck();

The constructor is specified after the new operator in this line of code, and this is called an empty constructor. If you want to pass parameters to a constructor, you can do so by defining another version of the constructor, which is a topic that needs to be covered in the next section on polymorphism.

Polymorphism

Polymorphism is a complex word that, when broken down, equates to poly (“many”) and morph (“shape”); therefore, polymorphism means “many shape” or “many shapes.” Java allows you to write many versions of a function (or method) with different sets of parameters. When you write more than one version of a method, you have overloaded that method. Overloading is a technical programming term that describes polymorphism at work.

Tip

I have been using the terms function and method together up to this point. I will refer to method from this point forward. Just note that a method is the same as a function, and this applies to accessor/mutator functions (terms that are used by C++ programmers). Just remember: A property is a variable, and a method is a function.

The complete truck class source code listing demonstrates polymorphism. Note the constructor, truck(), which has been overloaded once with an alternative version with the following syntax:

public truck(String make, String model, String engine, int towing)

You will probably not pass all of the data to a class in this manner all at once, as it is not usually very practical. You may pass any values to the constructor that you think will help with the initialization of the object that is being instantiated, but keep in mind that there are methods available for reading and changing those variables (or properties) as well.

Do you see how the default constructor includes several method calls to set the private variables to some initial values? This is a good practice to do when creating a class definition, because it eliminates the chance of a null-pointer runtime error from occurring—which is common when working with strings that have not yet been set to a value. I’ve decided not to include a string length check in the set functions to make the source code easier to read, but this sort of built-in error handling is a good idea.

public class truck extends vehicle {
    private String model;
    private String engine;
    private int towingcapacity;
    public truck() {
        setMake("make");
        setNumWheels(4);
        setModel("model");
        setEngine("engine");
        setTowingCapacity(0);
    }

    public truck(String make, String model, String engine, int towing) {
        setMake(make);
        setModel(model);
        setEngine(engine);
        setTowingCapacity(towing);
    }

    public String getModel() {
        return model;
    }
    public void setModel(String newmodel) {
        model = newmodel;
    }

    public String getEngine() {
        return engine;
    }
    public void setEngine(String newengine) {
        engine = newengine;
    }

    public int getTowingCapacity() {
        return towingcapacity;
    }
    public void setTowingCapacity(int value) {
        towingcapacity = value;
    }
}

Now let’s make some changes to the main source code in the SimpleClass.java file. This is the part of the program that consumes, or uses, the vehicle and truck classes. Here is the complete listing:

import java.lang.*;
import javax.swing.*;
import java.awt.*;

public class SimpleClass extends JFrame {
    vehicle car;
    truck lightning;

    public SimpleClass() {
        super("SimpleClass");
        setSize(600,400);
        setVisible(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //initialize a vehicle object
        car = new vehicle();
        car.setMake("Ford");
        car.setNumWheels(4);
        //initialize a truck object using a constructor
        lightning = new truck("Ford SVT", "F-150 Lightning",
            "5.4L Triton V8", 7700);
        lightning.
    }

    public void paint(Graphics g) {
        //let's use a nice big font
        g.setFont(new Font("Verdana", Font.BOLD, 12));

        //display the car info
        g.drawString("Car make: " + car.getMake(), 20, 50);
        g.drawString("Number of wheels: " + car.getNumWheels(), 20, 70);

        //display the truck info
        g.drawString("Truck make: " + lightning.getMake(), 20, 90);
        g.drawString("Truck model: " + lightning.getModel(), 20, 110);
        g.drawString("Truck engine: " + lightning.getEngine(), 20, 130);
        g.drawString("Truck towing capacity: " +
                     lightning.getTowingCapacity(), 20, 150);
    }

    public static void main(String[] args) {
        new SimpleClass();
    }
}

What is the most significant part of this program that might seem unusual or surprising? Well, take a look at those last few lines of code where the truck information is displayed on the screen. The truck is using a method called getMake() that is not even defined in the truck class; this is a method found only in the vehicle class, from which the truck class was inherited. That is the real power of inheritance—the ability to reuse functionality while enhancing existing classes.

I have added the truck class to the SimpleClass program, which is where the vehicle class may also be found. You can open the SimpleClass project from the companion website materials (www.courseptr.com/downloads) in the sourceschapter02 folder. Figure 2.3 shows the output from the current version of the program up to this point.

The SimpleClass program now demonstrates inheritance with the truck class.

Figure 2.3. The SimpleClass program now demonstrates inheritance with the truck class.

What You Have Learned

This chapter provided an overview of the basics of Java programming. You learned about the differences between a Java application and a Java applet, and how to write programs of each type and then compile and run them. You learned the basics of object-oriented programming and many other Java programming issues that will be helpful in later chapters. Specifically, this chapter covered:

  • How to write a Java application

  • How to write a Java applet

  • How to compile a Java program

Review Questions

The following questions will help you to determine how well you have learned the subjects discussed in this chapter. The answers are provided in Appendix A, “Chapter Quiz Answers.”

1.

What is the name of the JDK tool used to compile Java programs?

2.

Which JDK command-line tool is used to run a Java application?

3.

Which JDK command-line tool is used to run a Java applet?

4.

What are two good, free Java IDEs recommended in this chapter?

5.

Encapsulation, polymorphism, and inheritance are the keys to what programming methodology?

6.

What’s the main difference between a Java application and an applet?

7.

Which method of the Graphics class can you use to print a text message on the screen?

8.

How many bits make up a Java integer (the int data type)?

9.

How many bits are there in a Java long integer (the long data type)?

10.

What programming language was Java based on?

On Your Own

Use the following exercises to test your grasp of the material covered in this chapter.

Exercise 1

Write your own Java class and then use it to extend an inherited class to try out the concepts of inheritance and encapsulation.

Exercise 2

Modify your new class by adding some methods that demonstrate the concept of polymorphism by writing several versions of the same method with different sets of parameters.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.158.173