Home > Articles > Programming > Java

Find the Bug in this Java Program

This chapter from Adam Barr includes flawed Java programs for you to examine, providing great practice at troubleshooting these programs.
This chapter is from the book

Brief Summary of Java

Java programs are compiled into an intermediate format, known as bytecode, and then run through an interpreter that executes in a Java Virtual Machine (JVM).

The basic syntax of Java is similar to C and C++. All white space is treated equally, indent level does not matter, statements end in a semicolon, and blocks of code are enclosed between { and }.

Comments are enclosed between /* and */, or else begin with //, in which case the rest of the line is a comment.

Data Types and Variables

The integer data types are byte, short, int, and long, which correspond to numbers of 8, 16, 32, and 64 bits. The types float and double store floating-point numbers; char stores a 16-bit Unicode character, and boolean can hold one of two values, true or false.

Variables are declared with a type and name, as in the following:

int myint;

They can be initialized at the same time:

char delimeter = '/';
boolean finished = false;

Variables can be declared anywhere they are used. The scope of a variable usually extends to the end of the code block it was declared in.

Java allows variables to be converted between different numeric types by casting, as in the following:

int a;
double d = (double)a;

You can also cast between objects, but that is beyond the scope of this book.

Variables can be declared as final, which means that their value cannot be changed after it is initialized:

final int MAX_LEN = 128;

Arithmetic expressions in Java are straightforward, with % used for modulo:

k = a + b;
remainder = tot % users;

The ++ and -- operators exist. If they are used in prefix notation, the expression is evaluated after the operation is done. In postfix notation, the expression is evaluated before the operation is complete. So, with the following code

d = 4;
e = ++d;
f = e--;

e and f are both set to 5.

Strings (and Objects)

Beyond the basic data types, everything in Java is declared as a class. A class is a grouping of variables and methods (functions that operate on those variables). The word object is often used to refer to a class, but technically, a class is a description of an object and an instance is an actual object.

You can define your own classes; Java includes many predefined ones. One such class is String (or more precisely, java.lang.String), which is used to store a constant string. Strings in Java are not just arrays of characters—they are a class that has defined methods for accessing and modifying the characters.

The String class can serve as an example of how Java objects are used. A String can be created from an array of characters, as follows:

char[] myArray = { 'a', 'b', 'c' };
String myString = new String(myArray);

The expression new String(myArray) invokes what is called a constructor for the class String. Constructors create a new instance of an object, optionally taking parameters. How many parameters a constructor takes, and the type and order of those parameters, are part of the constructor's signature. Multiple constructors can exist for a given class as long as they have different signatures. For example, another constructor for String is called as follows:

String myString = new String(myArray, 2, 1);

That is, specifying an offset and count within myArray. You can also call

String myString = new String();

This creates an empty string. (A String cannot be changed after it's initialized, so it would stay empty.) The String class actually has nine constructors, plus two more obsolete ones.

When Java sees a literal string in double quotes, it automatically creates a String object, so you can write the following:

String newString = "text";

This is actually an assignment of one String to another. This automatic creation of an object from a literal is unique to the String class (all other literals, such as numbers, become primitive types), but it sure is convenient.

No destructors exist in Java; objects are destroyed by the garbage collector at some point after the last reference to them is removed (often because the variables holding that reference go out of scope). A variable can be assigned a keyword null to force a reference it is holding to be removed:

anotherString = null;

However, the garbage collector makes no guarantees about how soon an object will be destroyed once there are no references to it.

Java does not have explicit pointers; in a sense, all variables that refer to objects are pointers. When you assign between two objects of the same type, you actually assign a reference to the object on the right-hand side. To create a new instance of an object, you need to call one of its constructors:

myObject a, b;
a = b;                 // reference
a = new myObject(b);   // create a new object

Classes define methods that can be called on an instance of that class. For example, the String class has a method length() that returns the length of the string:

String j = "abc123";
x = j.length();

As previously mentioned, a String cannot change after it's initialized. Java has another class, StringBuffer, which holds strings that can change. A StringBuffer can be constructed from a String, or from a length, which specifies how many characters of capacity it should start with:

StringBuffer sb1 = new StringBuffer("howdy");
StringBuffer sb2 = new StringBuffer(100);

StringBuffer has a variety of methods on it:

sb.append("more data");
char c = sb.charAt(12);
sb.reverse();

In Java, the + operator can concatenate strings together. A sequence such as the following

String greeting = "Hello";
greeting = greeting + " there";

is legal. Because the original String that greeting points to cannot be modified, the concatenation actually involves the creation of a new String, which greeting is then set to point to. Therefore, the reference to the original "Hello" string is removed, which eventually causes it to be destroyed.

TIP

The concatenation statement also involves some more behind-the-scenes magic by the compiler. It creates a temporary StringBuffer, then calls the StringBuffer.append() method for each expression separated by a + sign, then calls StringBuffer.toString() to convert it back to the result String. As with the automatic creation of String objects from constant strings, this is a special case on the part of Java, but is there because string concatenation is so useful.

StringBuffer.append() is overloaded, so it can be passed any primitive type. Thus, you can call the following

int j = 4;
String b = "Value is" + j;

and b will equal "Value is 4". In fact, StringBuffer.append() works for any object by appending the result of the object's toString() method, which can be overridden as needed by the author of the object's class.

Arrays

Arrays in Java are declared with square brackets:

int[] intArray;

The array then has to be created:

intArray = new int[10];

intArray would then be indexed from 0 to 9.

Arrays can also be created at declaration time, if values are specified using an array initializer:

int[] array2 = { 5, 4, 3, 2, 1 };

You can't explicitly specify the length in that case because it's determined from how many values are provided.

You can get the number of elements in an array:

k = array2.length;

Note that this is not a method, so no parentheses appear after length.

Arrays can also hold objects, so you can declare the following:

MyObject[] objarray;

This would then be created as follows (this could be combined with the declaration):

objarray = new MyObject[5];

It is important to note that this creates only the array. You still need to create the five objects:

for (k = 0; k < 5; k++) {
    objarray[k] = new MyObject();
}

To create subarrays, create an array where each element is an array. The first array can be declared and created in one step

int[][] bigArray = new int[6][];

and then each subarray needs to be created (each one can be a different length, in fact):

for (m = 0; m < 6; m++) {
    bigArray[m] = new int[20];
}

You can initialize arrays when they are declared:

short[][] shortArray = { { 1, 2, 3 },  { 4 },  { 5 , 6 } };

After that, shortArray[0] would be an array of three elements, shortArray[1] would be an array of one element, and shortArray[2] would be an array of two elements.

Finally, if the entries in the arrays are objects, they also have to be constructed, as shown here:

final int XDIM = 6;
final int YDIM = 10;
SomeObj[][] oa;
oa = new SomeObj[XDIM][];
for (int i = 0; i < XDIM; i++) {
    oa[i] = new SomeObj[YDIM];
    for (int j = 0; j < YDIM; j++) {
        oa[i][j] = new SomeObj();
    }
}

Conditionals

Java conditionals use the same if/else syntax as C:

if (j == 5) {
    // do something
} else {
    // do something else
}

The switch statement is also the same, with explicit break statements required, and a default case:

switch (newChar) {
    case "@":
        process_at();
        break;
    case ".":
        process_dot();
        break;
    default: 
        ignore();
}

Loops

Looping is done with for, while, and do/while:

while (k > 8) {
    do_processing();
}

do {
    eof = get_line();
} while (eof != true);

break breaks out of a loop, and continue jumps to the next iteration. A label can be added to break or continue to specify which loop it refers to:

outerloop:
for (x = 0; x < 20; x++) {
    for (y = x; y < 20; y++) {
        if (something) {
            break outerloop;
        }
    }
}

outerloop: is a label for the loop and the statement break outerloop; breaks out of the labeled loop. It does not jump to the point where the outerloop: label exists in the code.

Classes

A class is defined as follows:

class MyClass {
    private int a;
    public StringBuffer b;
    public MyClass(int j) {
        a = j;
        b = new StringBuffer(j);
    }
    public MyClass(String s) {
        a = s.length();
        b = new StringBuffer(s);
    }
    public int getLength() {
        return a;
    }
}

a and b are member variables in the class. a is defined with an access specifier of private, which means that it is hidden from the view of external code. b is public, which means that anyone can access it if they have an instance of MyClass. For example

MyClass mc = new MyClass("hello");
String abc = mc.b;__// this is allowed, b is public
int def = mc.a;___// this is NOT allowed, a is private

We'll get back to access specifiers within the next few paragraphs. For now, note that MyClass has two constructors, one of which takes an int as a parameter, and the other takes a String (the second one is the one called in the previous code sample). Both constructors initialize a and b. Variables can also be initialized when they are declared, so b could have been declared as follows:

public StringBuffer b = new StringBuffer();

Although, for this class, that would not be necessary because every constructor initializes b.

Classes can also inherit from another class. A subclass inherits all the state and behavior of its superclass (but not the constructors), although it can override methods by providing new ones with the same name (unless those methods were declared with the final keyword).

Inheritance is indicated by the extends keyword:

abstract class Polygon {
    Point[] points;
    abstract int getcount();
}

class Triangle extends Polygon {
    public Triangle() {
        points = new Point[3];
    }
    int getcount() { return 3 };
}

The access specifier of a class variable can be public, private, protected, or package (the default). public means that any code can access it; private means that only methods in the class itself can access it; package means that any code in the same "package" (which is a way to group classes) can access it.

A variable marked protected can be accessed by the class, subclasses, and all classes in the same package. Actually, to be more precise, subclasses can only access a protected member inherited from a superclass when the object is an instance of the subclass (which it usually will be). They can't modify an instance of the superclass itself. (If you didn't catch all that, don't worry too much about it.)

Members of a class (variables or methods) can be declared with the keyword static, which makes them "class members," as opposed to "instance members," which is the case that's been described so far. Class variables and class methods exist just once, as opposed to once per instance. For example, a class could assign unique identifiers to each instance it creates, as shown here:

class ImportantObject {
    private static int nextcounter = 0;
    private int counter;
    public ImportantObject() {
        counter = nextcounter++;
    }
    // continues...
}

Each instance of the class has its own counter member, but there is only one global nextcounter.

A method on a class can be declared abstract, which means that it defines the parameters and return value, but has no actual implementation. A class can also be declared abstract; this is required if it defines at least one abstract method. (It is also required if a class does not provide implementation for any abstract methods declared in its superclasses.) An abstract class cannot itself be instantiated—it exists to ensure that subclasses follow the "contract" that it defines.

Closely related to classes are interfaces. The main difference between an interface and an abstract class is that all the methods on an interface must be abstract:

public interface identify {
    String getName();
}

Other classes can now support an interface using the implements keyword. Unlike inheritance, where a class can only inherit from one class, classes can implement as many interfaces as they like, as long as they provide implementations of all the interfaces' methods (or are declared abstract):

class SomeClass implements identify {
    final String name = "SomeClass";
    String getName() { return name };
    // rest of class follows...
}

A class with only public member variables—and no methods—can be used to group variables by name, similar to C structures:

class Record {
    public String name;
    public int id;
    public int privilege;
}

Record r = new Record();
r.name = "Joe";
r.id = 12;
r.privilege = 3;

Java likely has a class for almost any standard operation you want to do; the documentation lists constructors and methods. For example, classes exist that wrap all the primitive types, such as this one that wraps the short primitive in a class called Short (note the capital "S" on the class name), and provides various useful methods:

Short s = new Short(12);
String str = s.toString();

I won't go into more details about specific classes, except as needed in the examples.

Exceptions

Java supports exceptions, which are objects that can be caught:

try {
    file = new FileInputStream("data.tmp");
} catch (FileNotFoundException e) {
    System.err.println("Exception " + e.getMessage());
} finally {
    // cleanup code
}

A try can have multiple catch blocks, each catching a different exception. (There is a hierarchy of exception classes, leading back to a class called Throwable. A catch block that catches a particular exception also catches any exceptions that are subclasses of that exception.)

If an exception happens and is caught, the catch block executes. The finally block always executes, whether or not an exception happens, and is usually used for cleanup code.

You can create and throw exceptions:

if (bytesleft == 0) {
    throw new EOFException();
}

Java requires that methods that can throw an exception specify it in the declaration of the method, using the throws keyword:

public void read_file(File file)
            throws IOException {
    if (!check_valid(file)) {
        throw new IOException("check_valid() failed");
    }
}

Method declarations must also list any exceptions that can be thrown by methods they call, unless they catch the exception. Thus, a method that called read_file() (as defined above) would need to either put it in a try block with an associated catch block that caught IOException, or specify in its own declaration that it throws IOException. (This "catch or specify" rule does not apply to a class of exceptions known as runtime exceptions, which inherit from the class RuntimeException. This rule is detailed in the Java documentation.)

Importing Other Code

To use a class, you must import the package that defines it. This is specified in the documentation of the class. For example, to use the Timer class, include the following in the code:

import java.util.Timer;

This can include a wildcard:

import java.util.*;

Command-Line Applications and Applets

The examples used in this chapter are split between command-line applications and applets designed to run in a web browser. A command-line application has to contain a class that implements a main()method, which must be defined as public static, return type void, and receive the command-line parameters as an array of String objects called args (the first element in args is the first parameter, etc.):

public class MyApplication {
    public static void main(String[] args) {
        for (int j = 0; j < args.length; j++) {
            System.out.println(args[j]);
        }
    }
}

An applet inherits from a class called Applet:

public class MyApplet extends Applet {
    public void paint(Graphics g) {
       g.drawString("Testing 123", 10, 10);
    }
}

The paint() method is overridden from a superclass a few levels up from Applet, and is used to display on the screen. The Graphics class has many methods used to draw lines and shapes, display text, change color, and so on.

InformIT Promotional Mailings & Special Offers

I would like to receive exclusive offers and hear about products from InformIT and its family of brands. I can unsubscribe at any time.

Overview


Pearson Education, Inc., 221 River Street, Hoboken, New Jersey 07030, (Pearson) presents this site to provide information about products and services that can be purchased through this site.

This privacy notice provides an overview of our commitment to privacy and describes how we collect, protect, use and share personal information collected through this site. Please note that other Pearson websites and online products and services have their own separate privacy policies.

Collection and Use of Information


To conduct business and deliver products and services, Pearson collects and uses personal information in several ways in connection with this site, including:

Questions and Inquiries

For inquiries and questions, we collect the inquiry or question, together with name, contact details (email address, phone number and mailing address) and any other additional information voluntarily submitted to us through a Contact Us form or an email. We use this information to address the inquiry and respond to the question.

Online Store

For orders and purchases placed through our online store on this site, we collect order details, name, institution name and address (if applicable), email address, phone number, shipping and billing addresses, credit/debit card information, shipping options and any instructions. We use this information to complete transactions, fulfill orders, communicate with individuals placing orders or visiting the online store, and for related purposes.

Surveys

Pearson may offer opportunities to provide feedback or participate in surveys, including surveys evaluating Pearson products, services or sites. Participation is voluntary. Pearson collects information requested in the survey questions and uses the information to evaluate, support, maintain and improve products, services or sites, develop new products and services, conduct educational research and for other purposes specified in the survey.

Contests and Drawings

Occasionally, we may sponsor a contest or drawing. Participation is optional. Pearson collects name, contact information and other information specified on the entry form for the contest or drawing to conduct the contest or drawing. Pearson may collect additional personal information from the winners of a contest or drawing in order to award the prize and for tax reporting purposes, as required by law.

Newsletters

If you have elected to receive email newsletters or promotional mailings and special offers but want to unsubscribe, simply email information@informit.com.

Service Announcements

On rare occasions it is necessary to send out a strictly service related announcement. For instance, if our service is temporarily suspended for maintenance we might send users an email. Generally, users may not opt-out of these communications, though they can deactivate their account information. However, these communications are not promotional in nature.

Customer Service

We communicate with users on a regular basis to provide requested services and in regard to issues relating to their account we reply via email or phone in accordance with the users' wishes when a user submits their information through our Contact Us form.

Other Collection and Use of Information


Application and System Logs

Pearson automatically collects log data to help ensure the delivery, availability and security of this site. Log data may include technical information about how a user or visitor connected to this site, such as browser type, type of computer/device, operating system, internet service provider and IP address. We use this information for support purposes and to monitor the health of the site, identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents and appropriately scale computing resources.

Web Analytics

Pearson may use third party web trend analytical services, including Google Analytics, to collect visitor information, such as IP addresses, browser types, referring pages, pages visited and time spent on a particular site. While these analytical services collect and report information on an anonymous basis, they may use cookies to gather web trend information. The information gathered may enable Pearson (but not the third party web trend services) to link information with application and system log data. Pearson uses this information for system administration and to identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents, appropriately scale computing resources and otherwise support and deliver this site and its services.

Cookies and Related Technologies

This site uses cookies and similar technologies to personalize content, measure traffic patterns, control security, track use and access of information on this site, and provide interest-based messages and advertising. Users can manage and block the use of cookies through their browser. Disabling or blocking certain cookies may limit the functionality of this site.

Do Not Track

This site currently does not respond to Do Not Track signals.

Security


Pearson uses appropriate physical, administrative and technical security measures to protect personal information from unauthorized access, use and disclosure.

Children


This site is not directed to children under the age of 13.

Marketing


Pearson may send or direct marketing communications to users, provided that

  • Pearson will not use personal information collected or processed as a K-12 school service provider for the purpose of directed or targeted advertising.
  • Such marketing is consistent with applicable law and Pearson's legal obligations.
  • Pearson will not knowingly direct or send marketing communications to an individual who has expressed a preference not to receive marketing.
  • Where required by applicable law, express or implied consent to marketing exists and has not been withdrawn.

Pearson may provide personal information to a third party service provider on a restricted basis to provide marketing solely on behalf of Pearson or an affiliate or customer for whom Pearson is a service provider. Marketing preferences may be changed at any time.

Correcting/Updating Personal Information


If a user's personally identifiable information changes (such as your postal address or email address), we provide a way to correct or update that user's personal data provided to us. This can be done on the Account page. If a user no longer desires our service and desires to delete his or her account, please contact us at customer-service@informit.com and we will process the deletion of a user's account.

Choice/Opt-out


Users can always make an informed choice as to whether they should proceed with certain services offered by InformIT. If you choose to remove yourself from our mailing list(s) simply visit the following page and uncheck any communication you no longer want to receive: www.informit.com/u.aspx.

Sale of Personal Information


Pearson does not rent or sell personal information in exchange for any payment of money.

While Pearson does not sell personal information, as defined in Nevada law, Nevada residents may email a request for no sale of their personal information to NevadaDesignatedRequest@pearson.com.

Supplemental Privacy Statement for California Residents


California residents should read our Supplemental privacy statement for California residents in conjunction with this Privacy Notice. The Supplemental privacy statement for California residents explains Pearson's commitment to comply with California law and applies to personal information of California residents collected in connection with this site and the Services.

Sharing and Disclosure


Pearson may disclose personal information, as follows:

  • As required by law.
  • With the consent of the individual (or their parent, if the individual is a minor)
  • In response to a subpoena, court order or legal process, to the extent permitted or required by law
  • To protect the security and safety of individuals, data, assets and systems, consistent with applicable law
  • In connection the sale, joint venture or other transfer of some or all of its company or assets, subject to the provisions of this Privacy Notice
  • To investigate or address actual or suspected fraud or other illegal activities
  • To exercise its legal rights, including enforcement of the Terms of Use for this site or another contract
  • To affiliated Pearson companies and other companies and organizations who perform work for Pearson and are obligated to protect the privacy of personal information consistent with this Privacy Notice
  • To a school, organization, company or government agency, where Pearson collects or processes the personal information in a school setting or on behalf of such organization, company or government agency.

Links


This web site contains links to other sites. Please be aware that we are not responsible for the privacy practices of such other sites. We encourage our users to be aware when they leave our site and to read the privacy statements of each and every web site that collects Personal Information. This privacy statement applies solely to information collected by this web site.

Requests and Contact


Please contact us about this Privacy Notice or if you have any requests or questions relating to the privacy of your personal information.

Changes to this Privacy Notice


We may revise this Privacy Notice through an updated posting. We will identify the effective date of the revision in the posting. Often, updates are made to provide greater clarity or to comply with changes in regulatory requirements. If the updates involve material changes to the collection, protection, use or disclosure of Personal Information, Pearson will provide notice of the change through a conspicuous notice on this site or other appropriate way. Continued use of the site after the effective date of a posted revision evidences acceptance. Please contact us if you have questions or concerns about the Privacy Notice or any objection to any revisions.

Last Update: November 17, 2020