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