Draft Java Coding Standard
written by Doug Lea
and released to the public domain.
Contents
- Structure and Documentation
- Standard ways to write and document constructions.
- Naming conventions
- Standard ways to name identifiers (class names,
method names, variable names, etc).
- Recommendations
- Some rules of thumb that tend to avoid common errors and
development obstacles. You can use these guidelines to make your
own design and coding checklists to be used in
retrospective code clean-up or when classes need to be used in new
contexts or placed in reusable libraries.
- Related Documents
- Links to other style guidelines etc.
The form of these guidelines is based on example coding standards and
checklists in Watts
Humphrey's book
A Discipline for Software Engineering,
Addison-Wesley, 1995, along with feedback from people using previous
versions of this document.
Structure and Documentation
Packages
Create a new java package
for each self-contained
project or group of related functionality. Create and use
directories in accord with java package
conventions.
Consider writing an index.html
file in each directory
briefly outlining the purpose and structure of the package.
Program Files
Place each class in a separate file. This applies even to
non-public classes (which are allowed by the Java compiler to be
placed in the same file as the main class using them) except in the
case of one-shot usages where the non-public class cannot
conceivably be used outside of its context.
Begin each file with a comment including:
- The file name and/or related identifying information
including, if applicable, copyright information.
- A history table listing dates, authors, and summaries of
changes.
- If the file contains more than one class, list the classes,
along with a very brief description of each.
- If the file introduces a principal entry point for a
package
, briefly describe the rationale for
constructing the package.
Immediately follow each file header with:
- The
package
name
- The
import
list.
Example:
/*
File: Example.java
Date Author Changes
Sep 1 95 Doug Lea Created
Sep 13 95 Doug Lea Added new doc conventions
*/
package demo;
import java.util.NoSuchElementException;
Classes and Interfaces
Write all /** ... **/
comments using javadoc
conventions. (Even though not required by javadoc, end each
/**
comment with **/
to make it easier to
read and check.)
Preface each class with a /** ... **/
comment describing
the purpose of the class, guaranteed invariants, usage instructions,
and/or usage examples. Also include any reminders or disclaimers
about required or desired improvements. Use HTML format, with added
tags:
-
@author
author-name
-
@version
version number of class
-
@see
string
-
@see
URL
-
@see
classname#methodname
Example:
/**
* A class representing a window on the screen.
* For example:
* <pre>
* Window win = new Window(parent);
* win.show();
* </pre>
*
* @see awt.BaseWindow
* @see awt.Button
* @version 1.2 31 Jan 1995
* @author Bozo the Clown
**/
class Window extends BaseWindow {
...
}
Class Variables
Use javadoc conventions to describe nature, purpose,
constraints, and usage of instances variables and static variables.
Use HTML format, with added tags:
-
@see
string
-
@see
URL
-
@see
classname#methodname
Example:
/**
* The current number of elements.
* must be non-negative, and less than or equal to capacity.
**/
protected int count_;
Methods
Use javadoc conventions to describe nature, purpose,
preconditions, effects, algorithmic notes, usage instructions,
reminders, etc. Use HTML format, with added tags:
-
@param
paramName description. (Note: In
alpha versions of Java, this is listed as @arg
,
not @param
.)
-
@return
description of return value
-
@exception
exceptionName description
-
@see
string
-
@see
URL
-
@see
classname#methodname
Be as precise as reasonably possible in documenting effects.
Here are some conventions and practices for semi-formal specifications.
-
@return condition:
(condition)
- describes postconditions and effects true upon return of a method.
-
@exception
exceptionName IF
(condition)
- indicates the conditions under
which each exception can be thrown. Include conditions under which
uncommon unchecked (undeclared) exceptions can be thrown.
-
@param
paramname WHERE
(condition)
- indicates restrictions on argument values.
Alternatively, if so implemented, list restrictions alongside the
resulting exceptions, for example
IllegalArgumentException
. In particular, indicate
whether reference arguments are allowed to be null
.
-
WHEN
(condition)
- indicates that actions
use guarded
waits
until the condition holds.
-
RELY
(condition)
- describes
assumptions about execution context. In particular, relying on
other actions in other threads to terminate or provide
notifications.
-
GENERATE
T
- to describe new entities (for the main example,
Threads
)
constructed in the course of the method.
-
ATOMIC
- indicates whether actions are guaranteed to be uninterfered
with by actions in other threads
(normally as implemented via
synchronized
methods or blocks).
-
PREV(obj)
- refers to the state of an object at the onset of a method.
-
OUT(message)
- describes messages (including
notifications such as
notifyAll
) that are
sent to other objects as required aspects of functionality, or
referrred to in describing the effects of other methods.
-
foreach (int i in lo .. hi)
predicate
- means that predicate holds for each value of i.
-
foreach (Object x in e)
predicate
- means
that the predicate holds for each element of a collection or
enumeration.
-
foreach (Type x)
predicate
- means that the
predicate holds for each instance of
Type
.
-
-->
- means `implies'.
-
unique
- means that the value is different than any other. For example,
a
unique
instance variable that always refers to an object
that is not referenced by any other object.
-
fixed
- means that the value is never changed after it is initialized.
-
EQUIVALENT to { code segment }
- documents convenience or specialized methods that can
be defined in terms of a few operations using other methods.
Example:
/**
* Insert element at front of the sequence
*
* @param element the element to add
* @return condition:
* <PRE>
* size() == PREV(this).size()+1 &&
* at(0).equals(element) &&
* foreach (int i in 1..size()-1) at(i).equals(PREV(this).at(i-1))
* </PRE>
**/
public void addFirst(Object element);
Local declarations, statements, and expressions
Use /* ... */
comments to describe algorithmic
details, notes, and related documentation that spans more than a
few code statements.
Example:
/*
* Strategy:
* 1. Find the node
* 2. Clone it
* 3. Ask inserter to add clone
* 4. If successful, delete node
*/
Use Running //
comments to clarify non-obvious code.
But don't bother adding such comments to obvious code;
instead try to make code obvious!
Example:
int index = -1; // -1 serves as flag meaning the index isn't valid
Or, often better:
static final int INVALID= -1;
int index = INVALID;
Use any consistent set of choices for code layout, including:
- Number of spaces to indent.
- Left-brace (``
{
'') placement at end of line or beginning
of next line.
- Maximum line length.
- Spill-over indentation for breaking up long lines.
- Declare all class variables in one place (by normal convention,
at the top of the class).
Naming Conventions
- packages
-
lowercase
.
Consider using the recommended
domain-based conventions described in the
Java Language Specification, page 107 as prefixes.
(For example, EDU.oswego.cs.dl
.)
- files
- The java compiler enforces the convention that file names have the
same base name as the public class they define.
- classes:
-
CapitalizedWithInternalWordsAlsoCapitalized
- Exception class:
-
ClassNameEndsWithException
.
- Interface. When necessary to distinguish from similarly
named classes:
-
InterfaceNameEndsWithIfc
.
- Class. When necessary to distinguish from similarly
named interfaces:
-
ClassNameEndsWithImpl
OR
-
ClassNameEndsWithObject
- constants (finals):
-
UPPER_CASE_WITH_UNDERSCORES
- private or protected: (pick one!)
-
firstWordLowerCaseButInternalWordsCapitalized
OR
-
trailingUnderscore_
, OR
-
thisVar
(i.e. prefix with this), OR
-
myVar
(i.e. prefix with my), OR
-
fVar
(i.e. prefix with f)
- static private or protected:
-
firstWordLowerCaseButInternalWordsCapitalized
OR
-
twoTrailingUnderscores__
- local variables:
-
firstWordLowerCaseButInternalWordsCapitalized
OR
-
lower_case_with_underscores
- methods:
-
firstWordLowerCaseButInternalWordsCapitalized()
- factory method for objects of type X:
-
newX
- converter method that returns objects of type X:
-
toX
- method that reports an attribute x of type X:
-
X x()
or X getX()
.
- method that changes an attribute x of type X:
-
void x(X value)
or void setX(X value)
.
Recommendations
- Minimize
*
forms of import
. Be precise
about what you are importing. Check that all declared imports
are actually used.
- Rationale:
Otherwise readers of your code will have a hard time understanding
its context and dependencies. Some people even prefer not
using
import
at all (thus requiring that every
class reference be fully dot-qualified), which avoids all possible
ambiguity at the expense of requiring more source code changes if package
names change.
- When sensible, consider writing a
main
for the principal class
in each program file. The main
should provide a
simple unit test or demo.
- Rationale: Forms a basis for testing. Also provides usage examples.
- For self-standing application programs, the class with
main
should be separate from those containing normal classes.
- Rationale: Hard-wiring an application program in one of its
component class files hinders reuse.
- Consider writing template files for the most common kinds of
class files you create: Applets, library classes, application classes.
- Rationale: Simplifies conformance to coding standards.
- If you can conceive of someone else implementing a class's
functionality differently, define an interface, not an abstract
class. Generally, use abstract classes only when they are
``partially abstract''; i.e., they implement some functionality
that must be shared across all subclasses.
- Rationale:
Interfaces are more flexible than abstract classes. They support
multiple inheritance and can be used as `mixins' in otherwise
unrelated classes.
- Consider whether any class should implement
Cloneable
and/or Serializable
.
- Rationale: These are ``magic'' interfaces in Java, that automatically
add possibly-needed functionality only if so requested.
- Declare a class as
final
only if it is a subclass or
implementation of a class or interface declaring all of its
non-implementation-specific methods. (And similarly for
final methods).
- Rationale: Making a class final means that no one ever has a chance to
reimplement functionality. Defining it instead to be a subclass
of a base that is not final means that someone at least gets a
chance to subclass the base with an alternate implementation.
Which will essentially always happen in the long run.
- Never declare instance variables as public.
- Rationale: The standard OO reasons. Making variables public gives
up control over internal class structure. Also, methods cannot
assume that variables have valid values.
- Minimize reliance on implicit initializers for instance variables
(such as the fact that reference variables are initialized to
null
).
- Rationale: Minimizes initialization errors.
- Minimize statics (except for static final constants).
- Rationale: Static variables act like globals in non-OO languages.
They make methods more context-dependent, hide possible
side-effects, sometimes present synchronized access
problems. and are the source of fragile, non-extensible
constructions. Also, neither static variables nor methods are
overridable in any useful sense in subclasses.
- Generally prefer
long
to int
,
and double
to float
. But use
int
for compatibility with standard Java constructs
and classes (for the major example, array indexing, and all of
the things this implies, for example about maximum sizes of
arrays, etc).
- Rationale:
Arithmetic overflow and underflow can be 4 billion times less
likely with longs than
ints
; similarly, fewer
precision problems occur with doubles
than
floats
. On the other hand, because of limitations
in Java atomicity guarantees, use of longs and doubles must be
synchronized in cases where use of ints and floats sometimes
would not be.
- Use
final
and/or comment conventions to indicate
whether instance variables
that never have their values
changed after construction are intended to be constant (immutable)
for the lifetime of the object (versus those that just so
happen not to get assigned in a class, but could in a subclass).
- Rationale:
Access to immutable instance variables generally does not
require any synchronization control, but others generally do.
- Generally prefer
protected
to private
.
- Rationale: Unless you have good reason for sealing-in a particular
strategy for using a variable or method, you might as well plan
for change via subclassing. On the other hand, this almost
always entails more work. Basing other code in a base class
around
protected
variables and methods is harder,
since you you have to either loosen or check assumptions about
their properties. (Note that in Java, protected
methods are also accessible from unrelated
classes in the same package. There is hardly ever any reason to
exploit this though.)
- Avoid unnecessary instance variable access and update methods.
Write
get/set
-style methods only when they are
intrinsic aspects of functionality.
- Rationale:
Most instance variables in most classes must maintain values
that are dependent on those of other instance
variables. Allowing them to be read or written in isolation
makes it harder to ensure that consistent sets of values are
always used.
- Minimize direct internal access to instance variables inside methods.
Use
protected
access and update methods instead (or
sometimes public
ones if they exist anyway).
- Rationale: While inconvenient and sometimes overkill, this allows
you to vary synchronization and notification policies associated
with variable access and change in the class and/or its
subclasses, which is otherwise a serious impediment to
extensiblity in concurrent OO programming. (Note: The
naming conventions for instance variables serve as an
annoying reminder of such issues.)
- Avoid giving a variable the same name as one in a superclass.
- Rationale: This is usually an error. If not, explain the intent.
- Prefer declaring arrays as
Type[] arrayName
rather than Type arrayName[]
.
- Rationale: The second form is just for incorrigible C prgrammers.
- Ensure that non-private
statics
have sensible values even if no instances
are ever created. (Similarly ensure that static
methods
can be executed sensibly.) Use static intitializers (static { ... }
) if necessary.
- Rationale: You cannot assume that non-private statics will be
accessed only after instances are constructed.
- Write methods that only do ``one thing''. In particular,
separate out methods that change object state from those that
just rely upon it. For a classic example in a
Stack
, prefer having two methods Object
top()
and void removeTop()
versus the single
method Object pop()
that does both.
- Rationale:
This simplifies (sometimes, makes even possible) concurrency
control and subclass-based extensions.
- Define return types as
void
unless they return
results that are not (easily) accessible otherwise. (i.e.,
hardly ever write ``return this
'').
- Rationale: While convenient, the resulting method cascades
(
a.meth1().meth2().meth3()
) can be the sources of
synchronization problems and other failed expectations about the
states of target objects.
- Avoid overloading methods on argument type. (Overriding on
arity is OK, as in having a one-argument version versus a two-argument
version). If you need to specialize behavior according
to the class of an argument, consider instead choosing
a general type for the
nominal argument type (often
Object
) and using
conditionals checking instanceof
. Alternatives
include techniques such as double-dispatching, or often best,
reformulating methods (and/or those of their arguments)
to remove dependence on exact argument type.
- Rationale: Java method resolution is static; based on
the listed types, not the actual types of argument. This is
compounded in the case of non-Object types with coercion
charts. In both cases, most programmers have not committed the
matching rules to memory. The results can be counterintuitive;
thus the source of subtle errors. For example, try to predict
the output of this. Then compile and run.
class Classifier {
String identify(Object x) { return "object"; }
String identify(Integer x) { return "integer"; }
}
class Relay {
String relay(Object obj) { return (new Classifier()).identify(obj); }
}
public class App {
public static void main(String[] args) {
Relay relayer = new Relay();
Integer i = new Integer(17);
System.out.println(relayer.relay(i));
}
}
- Declare all public methods as synchronized; or if not, describe the
assumed invocation context and/or rationale for lack of
synchronization.
- Rationale: In the absence of planning out a set of concurrency
control policies, declaring methods as synchronized at least
guarantees safety (although not necessarily liveness) in
concurrent contexts (every Java program is concurrent
to at least some minimal extent). With full synchronization of
all methods, the methods may lock up, but the object can never
enter in randomly inconsistent states (and thus engage in
stupidly or even dangerously wrong behaviors) due to concurrency
conflicts. If you are worried about efficiency problems due to
synchronization, learn enough about concurrent OO programming to
plan out more efficient and/or less deadlock-prone policies.
- Prefer
synchronized
methods to synchronized
blocks.
- Rationale: Better encsapsulation; less prone to subclassing
snags; can be more efficient.
- If you override Object.equals, also override Object.hashCode,
and vice-versa.
- Rationale: Essentially all containers and other utilities
that group or compare objects in ways depending on equality rely
on hashcodes to indicate possible equality.
- Override
readObject
and WriteObject
if a Serializable
class relies on any
state that could differ across processes, including, in
particular, hashCodes
and transient fields.
- Rationale: Otherwise, objects of the class will not transport properly.
- If you think that clone() may be called in a class
you write, then explicitly define it (and declare the class to
implement Cloneable
).
- Rationale: The default shallow-copy version of
clone
might not do what you want.
- Always document the fact that a method invokes
wait
- Rationale: Clients may need to take special actions to
avoid nested monitor calls.
- Whenever reasonable, define a default (no-argument) constructor
so objects can be created via Class.newInstance().
- Rationale: This allows classes of types unknown at compile
time to be dynamically loaded and instantiated (as is done for
example when loading unknown Applets from html pages).
- Prefer
abstract
methods in base classes to those
with default no-op implementations. (Also, if there is a common
default implementation, consider instead writing it as a
protected
method so that subclass authors can just
write a one-line implementation to call the default.)
- Rationale: The Java compiler will force subclass authors to
implement
abstract
methods, avoiding problems
occurring when they forget to do so but should have.
- Use method
equals
instead of operator ==
when
comparing objects. In particular, do not use ==
to
compare Strings
.
- Rationale: If someone defined an
equals
method
to compare objects, then they want you to use it. Otherwise, the
default implementation of Object.equals
is just to
use ==
.
- Always embed
wait
statements in while
loops that re-wait if the condition being waited for does not
hold.
- Rationale: When a
wait
wakes up, it does not know
if the condition it is waiting for is true or not.
- Use
notifyAll
instead of notify
or
resume
.
- Rationale:
Classes that use only
notify
can normally only
support at most one kind of wait condition across all methods in
the class and all possible subclasses. And unguarded
suspends/resumes
are even more fragile.
- Declare a local variable only at that point in the code where
you know what its initial value should be.
- Rationale: Minimizes bad assumptions about values of variables.
- Declare and initialize a new local variable rather
than reusing (reassigning) an existing one whose value happens to
no longer be used at that program point.
- Rationale: Minimizes bad assumptions about values of variables.
- Assign
null
to any reference variable that is
no longer being used. (This includes, especially, elements
of arrays.)
- Rationale: Enables garbage collection.
- Avoid assignments (``
=
'') inside if
and while
conditions.
- Rationale: There are almost always typos. The
java compiler catches cases where ``
=
'' should have
been ``==
'' except when the variable is a
boolean
.
- Document cases where the return value of a called method
is ignored.
- Rationale: These are typically errors. If it is by intention,
make the intent clear. A simple way to do this is:
int unused = obj.methodReturningInt(args);
- Ensure that there is ultimately a
catch
for
all unchecked exceptions that can be dealt with.
- Rationale: Java allows you to not bother declaring or
catching some common easily-handlable exceptions, for example
java.util.NoSuchElementException
. Declare and
catch them anyway.
- Embed casts in conditionals. For example:
-
C cx = null;
if (x instanceof C) cx = (C)x;
else evasiveAction();
Rationale: This forces you to consider what to do if
the object is not an instance of the intended class
rather than just generating a ClassCastException
.
- Document fragile constructions used solely for the sake of
optimization.
- Rationale: See
Jonathan Hardwick's Java Optimization pages.
- Do not require 100% conformance to rules of thumb such as
the ones listed here!
- Rationale: Java allows you program in ways that do not
conform to these rules for good reason. Sometimes they
provide the only reasonable ways to implement things. And
some of these rules make programs less efficient than they
might otherwise be, so are meant to be concientiously broken
when performance is an issue.
Related Documents
For some other standards and style guides, see
Doug Lea
Last modified: Wed Feb 23 18:26:38 EST 2000