Java Stylistic Conventions Java Stylistic Conventions Object-Oriented Programming with Java: An Introduction by David J. Barnes Published by Prentice-Hall Introduction Stylistic conventions are important for readers of your programs. On this page we outline some guidelines that we think are worth adopting. These are taken from my book Object-Oriented Programming with Java: An Introduction, published by Prentice Hall. Comments All programs should be properly commented. The Javadoc tool facilitates the automatic generation of program documentation where its conventions have been used. In particular, each class and method should be prefaced by a comment describing its overall purpose. For constructors and major methods, you should consider including the following items as part of their specification purpose argument descriptions result descriptions constraints exceptions thrown The following method illustrates these principles.
/** Locate the minimum value in the elements
* data[lower .. upper].
* Lower must be <= upper, and both must be within the
* range 0 .. data.length-1.
* @param data The data to be searched.
* @param lower The lowest index for the range to be searched.
* @param upper The highest index for the range to be searched.
* @return The minimum value.
* @throws IllegalRangeException if lower > upper, or either
* lower or upper is outside the bounds of data.
*/
public int locateMin(int[] data,int lower,int upper)
throws IllegalRangeException {
...
}
Statement comments should precede the statements to which they refer and not be appended to the ends of lines. It is preferable to comment a block of statements rather than each individually. Try to get into the habit of commenting as you write, rather than after the event. In the real world, there will not be time to comment once the program is `finished'. Both single-line comments (using //) and multi-line comment forms (using /* ... */) are equally acceptable. When the multi-line comment form is used, ensure that the closing comment symbol can be easily spotted, preferably by indenting it to the same level as the opening symbol, for instance
/* This comment
is a multi-line comment
that spans several lines.
*/
Some authors like to emphasize comments with further adornments such as
/* This comment
* is a multi-line comment
* that spans several lines.
*/
This is perfectly acceptable. Identifiers There is no right or wrong style of choice of identifiers, except that they should be accurately descriptive. The most important point is to be consistent. A variable should have a single purpose rather than being used for several different tasks, and its name should reflect that purpose. For instance: accountNumber, valueFound, studentName, etc. Avoid examples like
if(list.point() == -1)
when
if(list.getNumberOfItems() == 0)
is much clearer. A common style is that names of methods, attributes, method variables and formal arguments should have an initial lower-case letter, but a single upper-case letter at word boundaries (as in the examples). Class names should start with an upper-case letter and follow a similar convention at word boundaries, e.g. Ship, TemperatureController, PortAuthority. Public final class variables (public static final) should either be all upper-case names, or they should have an initial upper-case letter. The names for accessor and mutator methods should be based directly upon the name of the attribute to which they apply. They should have either a get or set prefix, followed by the name of the attribute with its first letter capitalized. It is hard for a single-character variable name to convey much information about its purpose so, in general, these should be avoided, with the following exceptions Loop-control variables in for-loops used to systematically iterate over a fixed range. The formal argument name of a simple set mutator method. The name will typically be the first letter of the attribute being mutated. In general, define method variables close to where they are first used, rather than bunching them all together at the start of a method. Make use of the fact that variables may be defined within nested blocks to ensure that a method variable's visibility is closely related to the part of a method in which it is used. Final Variables As far as possible, avoid the use of magic numbers in your programs. Instead, create a final variable for values of significance, e.g.
final int endOfList = -1;
final int meaning = 42;
final double MAXMARK = 100.0;
The only exceptions to this rule are the use of 0 and 1 as initializers and 1 as a simple step, although ++ and -- are more convenient. Where final variables could be of use to objects other than the one in which they are defined, they may be defined as public static final, for instance
class Date {
public static final int January = 0, ... ;
...
}
Some authors prefer to use completely upper-case names for final variables. Use the final specifier for variables for value will remain unchanged after initialization. Final attributes may be set directly in their declaration, in every constructor, or in an instance initializer. This can avoid the need to define a mutator for such an attribute. However, omitting a mutator could make it harder to check the validity of the attribute's value when it is set at instance construction time - validity checks will need to be included at each initialization point. In such circumstances, therefore, it might be worth not using a final designation and including a validity checking mutator. The mutator will be able to prevent the attribute's value being changed once set if the attribute is an object reference, by checking whether the attribute is already non-null. Fields defined within interfaces are always public static final. We recommend that these access modifiers are explicitly included in their definition. Indentation and Layout Try to keep lines no longer than 80 characters. Even though this limit dates from the ancient days of punch cards, longer lines often do not display well within some programs or windows. Use four spaces for each level of indentation, and use single blank lines freely in order to emphasize blocks of code, as in this example.
class ExampleClass {
public static final int LOW = -20, MEDIUM = 0, HIGH = 20;
public static final int DEFAULT = MEDIUM;
public ExampleClass(int initialValue){
if(howMany > DEFAULT){
setNumber(initialValue);
}
else{
setNumber(DEFAULT);
}
}
...
private void setNumber(int number){
this.number = number;
}
private int number;
}
Define methods before instance variables, and public methods before those with lesser visibility. Final static variables with public visibility may be defined at the beginning of the class. Break long lines immediately after operators in expressions and commas in argument lists. Indent the remaining part of the statement somewhat deeper than the current indentation level. Where practicable, indent to a level that relates the broken part to where it belongs on the previous line, as follows
VeryLongClassName evenLongerVariableName =
new VeryLongClassName("Say hello to auntie.");
Greeting introduction = new Greeting("Good morning,",32,'x',
new Point(8,105),
new Point(458,47));
Initializers and Anonymous Classes Long array initializers should be split over multiple lines, for instance
int[] values = {
3, 56, 23, 999, 101, -8, 3443, 23234, -9900,
45, -349730, 783,
};
It is common practice to include a trailing comma after the final value, as this makes it easier to add items at a later date. A typical layout for anonymous class definitions is as follows
button.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
...
}
});
Note the way in which the closing curly bracket is kept together with the closing parenthesis of the argument list. Curly Brackets Place the opening curly bracket at the end of class and method headers. A curly bracket following a class header is often separated from it by a single space. Indent the closing curly bracket of class and method bodies to the same level as the initial reserved word of the construct.
class ExampleClass {
public void method(){
...
}
}
Always use a pair of curly brackets with statements such as if-, while- and for-, even when the body of the construct contains a single statement
if(x > largest){
largest = x;
}
Place the opening curly bracket immediately following the condition of an if-statement, while-loop and for-loop. You might need to break a long condition over more than one line - do so after an operator and indent the broken line so that it starts beneath the expression that is broken, and further to the right than the statement immediately following.
if((month < rainfall.length) &&
(rainfall[month] > greatest)){
statement;
}
Increment and Decrement Operators Use the post-increment and post-decrement forms of the increment (x++) and decrement (x--) operators. Wherever possible, avoid using these operators where you are also using the value of the variable being modified. Instead, use separate statements in order to avoid possible confusion. For example, rather than writing
arr[index++] = reader.nextInt();
write
arr[index] = reader.nextInt();
index++;
In the first example, it is easy to miss the fact that index is being incremented in addition to the assignment being made. Switch Statement Use a switch statement in preference to a cascading if-else statement, where an arithmetic expression is to be checked against multiple constant values. The compiler is usually able to create a more efficient selection of the appropriate statements with a switch statement. Avoid over use of omitting break from cases to provide a fall through to the next case. When it is omitted, always include a comment to make clear that this is not an error. Exceptions Use checked exceptions whenever possible. Include a throws-clause for unchecked exceptions even though this is not mandatory. Take the opportunity to create sub classes of the basic Exception classes in order to give meaningful names to the types of errors that arise. These do not need to add additional attributes or behavior to their super class. Where such new exception classes are closing tied to a single throwing class, consider defining them as static nested classes within the throwing class. Use exceptions for `impossible routes' through methods. These will often be thrown in a final else-part of a validity-checking cascading if-else statement, or at the end of a result-returning method that should be unreachable in normal circumstances. These rules increase both the compiler's and the programmer's opportunities to ensure that exceptional circumstances are identified and recovery mechanisms put in place. Access Control Use the following forms of access control. An object's attributes should always be declared as private, rather than public, package or protected, even if the class is to be extended. Access to private attributes of primitive type may safely be granted via accessors with public access. Greater care should be taken when returning references to private attributes of object types since this could potentially allow circumvention of validating mutators via an alias. Use either public or protected access as appropriate. Use protected access mutators as a general rule, unless public access is required. Public access mutators should take particular care over validation of their arguments to ensure that an object is not left in an inconsistent state. Methods intended purely for internal use by a class should be protected, to make possible future extension by classes in other packages easier than with package access. General methods intended for the receipt of messages from other classes should be public. Constructors should normally provide either package or public access. If the class has package access, then no harm is done in providing public constructors. Classes and interfaces should have either package or public access, depending upon a program's requirement. These rules make it slightly easier to extend classes than it would be if the choice of access was simply between public and private, even when it has not been envisaged that a class might be extended in the future. Using at least protected access for its methods means that a package access class can be made extensible by classes in other packages relatively easily, by amending its constructors to at least protected level and giving public access to the class. The Main Method As little functionality as possible should be placed in the class holding the main method. The main method should mainly contain statements that create the initial objects that are going to interact to produce the purpose of the overall program. It is acceptable to place major functionality here if the program is so simple that it does not justify the creation of one or more classes. Only other static methods should appear in the class along with the main method. You should note that this minimalist approach is not taken by most other Java authors. Threads Avoid use of the volatile reserved word. It is only really needed to indicate potentially undisciplined access by multiple threads to an instance variable. Avoid this by defining such a variable as private, and provide synchronized accessor and mutator methods in the usual way. Do not overuse the synchronized modifier as it can result in unnecessary deadlock. Use it only where there is a clear need to lock an object against multiple thread access. Taken from the book, Object Oriented Programming with Java: An Introduction, by David J. Barnes. Published by Prentice Hall, January 2000. This document (http://www.cs.kent.ac.uk/~djb/oop/style.html) is maintained by: David Barnes, to whom any suggestions, comments and corrections should be addressed. © David J. Barnes and Prentice Hall, 1997-00. Last Updated: 28th February 2000 Created: 29th October 1997