Debugging is perhaps best done using a debugger such as those provided by integrated development environments. Nevertheless, many programmers debug programs by inserting print statements. This section describes some of the techniques that can be used in Java.
Printing number data and arrays
The methods
System.out.print
and System.out.println
are predefined for primitive types as well as for strings:int i = 1;
double d = 5.2;
System.out.print(i);
System.out.println(d);
Furthermore, automatic conversion to
String
type is performed by the concatenation operator +
:System.out.println("d = " + d + "and i = " + i);
The print statements can not print an entire array, so a method must be written:
public static void print(int[] a) {
for (int i = 0; i < a.length; i++)
System.out.print(a[i]);
System.out.println();
}
public static void main(String[] args) {
int[] a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
print(a);
}
Since the number of elements of an array can be large, it is better to write the method so that it inserts a newline after printing a fixed number of elements:
public static void print(int[] a) {
for (int i = 0; i < a.length; i++) {
System.out.print(a[i]);
if (i % 8 == 7) System.out.println();
}
System.out.println();
}
You can put this static method in a publicly accessible class and use it to print any integer array. Similar methods can be written for the other primitive types.
Converting objects to strings
Within the class
Object
, the root class for all other classes, a method toString
is declared. The default implementation will not give useful information, so it is a good idea to override it in each class that you write:class Node {
int key;
double value;
public String toString() {
return "The value at key " + key + " is " + value;
}
}
Then, you can simply call the print statements for any object of this class and the conversion to
String
is done automatically:Node node = new Node();
...
System.out.println(node);
The predefined class
java.util.Arrays
constains a lot of useful (static) methods for working with arrays, among them toString
methods for arrays whose elements are of any primitive type:int[] a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
System.out.println(java.util.Arrays.toString(a));
or
import java.util.Arrays;
...
System.out.println(Arrays.toString(a));
You will receive a predefined representation of the array (the elements are separated by commas), so if you want an alternate representation (such as printing on multiple lines) you will have to write your own print method as we did in the previous section.
An array of objects of any reference type can be printed by defing a single method since any object can be converted to
Object
:public static void print(Object[] a) {
for (int i = 0; i < a.length; i++)
System.out.print(a[i]);
System.out.println();
}
Node[] nodes = new Node[];
... // Create elements of the array
print(nodes);
or by calling the predefined method
deepToString
:Node[] nodes = new Node[];
... // Create elements of the array
System.out.println(java.util.Arrays.deepToString(node));
Forcing a stack trace
Suppose that you have isolated a bug to a certain method but you do not know which call of that method was responsible. You can force the interpreter to print a trace of the call stack by inserting the line:
new Exception().printStackTrace();
within the method. It creates a new object of type
Exception
and then invokes the method printStackTrace
. Since the exception is not thrown, the execution of the program proceeds with no interruption. A program can always be terminated by calling System.exit(n)
for an integer n
.Leave the debug statements in the program
Once you have found a bug, it is tempting to delete the print statements used for debugging, but it is better not to do so because you may need them in the future. You can comment out the statements that you don't need, but a better solution is to declare a global constant and then use it to turn the print statements on and off:
public class Global {
public static boolean DEBUG = false;
public static void print(int[] a) {...}
public static void print(Object[] a) {...}
}
if (Global.DEBUG) Global.print(nodes);
No comments:
Post a Comment