Java Programming Tips
---The sooner you begin to type code, the longer the program will take to finish, because careful design of the program must precede coding. This is particularly true of object-oriented programs.
---Develop your program's documentation at the same time that you develop its code, and include the pre- and postconditions in the documentation.
Use of Comments.
A well-written program should begin with a comment block that provides the name of the program, its author, and a description of what the program does.
Use of Indentation.
Indent the code within a block, and align the block's opening and closing braces. Use a comment to mark the end of a block of code.
Choice of Identifiers.
To make your program more readable, choose names that describe the purpose of the class, variable or method.
Method Call versus Method Definition.
Don't confuse method calls with method definitions. The definition specifies the method's actions. The method call takes the actions.
Class versus Instance Methods.
If a method is designed to be used by an object, it is referred to as an instance method. No modifier is needed to designate an instance method. Class methods, which are used infrequently compared to instance methods, must be declared static.
Parentheses.
Parentheses can (and should) be used to clarify any expression that seems ambiguous or to override Java's default precedence rules.
Parenthesize!
To avoid subtle bugs caused by Java's precedence and promotion rules, use parentheses to specify the order of evaluation in an expression.
Increment and Decrement Operators.
Because of their subtle behaviour, be careful how you use the unary increment and decrement operators. They are most appropriate and useful for incrementing and decrementing loop variables.
Numeric Types.
Java uses the int type for integer literals and double for real-number literals. When possible, using int and double for numeric variables and parameters reduces the number of implicit conversions a program would have to perform.
Don't Mix Types.
You can reduce the incidence of semantic errors caused by implicit type conversions if, whenever possible, you explicitly change all the literals in an expression to the same type.
Readability.
To make your programs more readable, use uppercase font for constant identifiers.
To make your programs more readable, use named constants instead of literal values.
Loop Indentation.
To make loops more readable, indent the loop body to set it off from the heading and to highlight which statement(s) will be repeated.
Multiway Selection.
A switch statement is typically used together with break to code a multiway selection structure.
Standard techniques.
Acquire and use standard programming techniques for standard programming problems. For example, using a temporary variable to swap the values of two variables is a standard technique.
Encapsulation.
Use methods wherever appropriate in your own code to encapsulate important sections of code and thereby reduce complexity.
Code Reuse.
Instead of reinventing the wheel, use library classes and methods whenever possible. These have been carefully designed by experienced programmers. Library code has been subjected to extensive testing.
StringBuffer.
A StringBuffer should be used instead of a String for any task that involves modifying a string.
Changing Each Character in a String.
Algorithms that require you to alter a string should use a StringBuffer to store the result.
Generality.
By using a component's size and font as the determining factors, you can center text on virtually any component. These values are available via the component's getFont() and getSize() methods.
Swapping Values.
It is necessary to use a temporary variable whenever you are swapping two values of any type in memory. The temporary variable holds the first value while you overwrite it with the second value.
Swapping Variables.
When swapping two memory elements, a temporary variable must be used to store one of the elements while its memory location is being overwritten.
Array Initializers.
Initializer (assignment) expressions can be used to assign initial values to relatively small arrays. For larger arrays, an initializer method should be designed.
Arranging catch Clauses.
Catch clauses should be arranged from most specific to most general. The Exception clause should always be the last in the sequence.
Choosing a Stream.
In choosing an appropriate stream for an I/O operation, DataInputStreams and DataOutputStreams normally are used for binary I/O. Reader and Writer streams normally are used for text I/O.
Buffering.
Buffered streams can improve a program's overall efficiency by reducing the amount of time it spends accessing relatively slow input or output devices.
Integer/String Conversion.
An integer can be converted to a String by writing it to a StringBuffer, which can then be output as an entire line of text. StringReader methods can read integer data from an ordinary String object.
Closing a File.
Even though Java will close any open files and streams when a program terminates normally, it is good programming practice to close the file yourself with a close() statement. This reduces the chances of damaging the file if the program terminates abnormally.
End of Line.
Remember that readLine() does not return the end-of-line character as part of the text it returns. If you want to print the text on separate lines, you must append \n.
Read Versus ReadLine.
Unless it is necessary to manipulate each character in the text file, reading a whole line at one time is more efficient and, therefore, preferable.
File Separators.
To help make your programs platform independent, use the File.separator constant instead of a literal value whenever you are specifying a path name.
The finally Block.
In coding a binary read loop, the try block is exited as soon as the EOFException is raised. Therefore, the close() statement must be placed in the finally clause, which is executed after the catch clause.
Object Serialization.
Java's serialization classes, ObjectOutputStream and ObjectInputStream, should be used whenever an object needs to be input or output from a stream.
Divide and Conquer.
Many programming problems can be solved by dividing them into smaller, simpler problems. For recursive solutions, finding the key to the subproblem often holds the solution to the original problem.
Subarray Parameter.
For methods that take an array argument, an int parameter can be used to designate the portion of the array that should be processed in the method.
Method Decomposition.
A task can be simplified by breaking it up into simpler subtasks, especially if you already have methods for solving one or more of the subtasks.
Swing Documentation.
Complete documentation of the Swing classes is available for downloading or browsing on Sun's Web site at http://java.sun.com/docs/ .
Grid Layout.
Make sure the number of components added to a GridLayout is equal to the number of rows times the number of columns.
Default Cases.
Although the order of the clauses in an if-else structure is usually not important, the default clause can sometimes be used to handle cases that can't be referenced by name.
Platform Dependence.
Thread implementation in Java is platform dependent. Adequate testing is necessary to ensure that a program will perform correctly on a given platform.
Thread Timing.
Unless they are explicitly synchronized, you cannot make any assumptions about when, or in what order, individual threads will execute, or where a thread might be interrupted or preempted during its execution.
Threading a GUI.
Creating a second thread within a GUI requires three steps:
(1) define the secondary thread to implement the Runnable interface,
(2) override its run() method, and
(3) incorporate some mechanism, such as a sleep() state, into the thread's run algorithm so that the GUI thread will periodically have a chance to run.
Critical Sections.
Java's monitor mechanism will ensure that while one thread is executing a synchronized method, no other thread can gain access to it. Even if the first thread is interrupted, when it resumes execution again it will be allowed to finish the synchronized method before other threads can access synchronized methods in that object.
Busy Waiting.
Java's wait/notify mechanism can be used effectively to eliminate busy waiting from a multithreaded application.
Modular Arithmetic.
Modular arithmetic (x % N) is useful for cycling repeatedly through the values 0, 1, …, N – 1.
Concatenation.
Concatenating an integer value (k) with a string lets you create file names of the form file1.gif, file2.gif, and so on.
Callback.
Communication between two objects can often be handled using a callback technique. One object is passed a reference to the other object. The first object uses the reference to call one of the public methods of the other object.
Socket Streams.
A socket has two streams, one for input and one for output.
The null Reference.
A null reference is useful for defining limit cases, such as an empty list or an uninstantiated object.
Terminating a Traversal.
In designing list-traversal algorithms where the reference, p, points to the nodes in the list, your exit condition should be p.getNext() == null if you need to refer to the last node in the list after the traversal loop exists. If you have finished processing the nodes when the loop exists, your exit condition should be p == null.
4
geminus