Variable naming and syntax conventions for Java

by Paul Constantinides

Introduction

This document describes a set of naming and syntax conventions tailored for the Java programming language. It is meant to supplement rather than replace resources such as Sun's Code Conventions for the Java Programming Language, or style guides such as The Elements of Java Style. The conventions described here augment and override some style choices described in these references, and therefore the references should be read and understood before proceding here.

These conventions are different from any of the ones I've found in the literature, and focus on naming and syntax. They are motivated by information design, and the aesthetic goal to make every section and line of code be identifiable, and understandable on its own.

The conventions described here are based on the work of a team of engineers. Credit is due to the other engineers who helped create, formalize, apply, and enforce many of these conventions over numerous versions of several large software products, and a manager who insisted on nothing less.

As a team, we benefited from having clear, consistent, easy to read, anonymous code. Our ability to collaborate and share code also benefited, as we were more focused on understanding our different approaches to problem solving, rather than the distraction of syntax. We shared the philosophy that product quality begins with code quality. These conventions emerged from the rigorous praxis of that philosophy.

Typed variable names

Simonyi's Hungarian Notation introduced the notion of encoding the type of a variable in the name. We leverage that notation here, by prefixing variable names with a string that indicates the type of that variable. This allows the type of the variable to be identifiable at a glance, and to differentiate between representations of the same notion (e.g. the String sWeatherUrl and the URL weatherUrl). The following conventions are used:

TypePrefixExample
booleanbbRunOnce
charccSeparator
doubleddDensity
floatffDuration
intnnCount
longllSuccesses
ObjectooUnknown
StringssFilename
StringBuffersbsbDocument
StringBuildersbsbDocument

In the case of certain other types, the type can be included in the variable name, although not necessarily prefixed. Often the most natural place in a descriptive variable name is at the end; prefixing can sometimes lead to a confusing sounding variable name in these cases.

TypeSubstringExample
ArrayarraynamesArray
IteratoriternamesIter
ListlistnamesList
ListIteratorlistIternamesListIter
MapmapnameToTitleMap
URLurlweatherUrl

Another candidate for this list is enum for objects of Enumeration type. This should, however, be used with caution, as starting with J2SE 5.0, enum this is a reserved word, and therefore can only appear as part of a longer variable name.

int iterators (as used in for loops, for example) should use the conventional naming: i, j, k, l, etc. (Some may choose to skip l due to the visual similarity between l and 1.)

Field prefixing

Another technique from Hungarian notation can be used in order to immediately differentiate field properties from local variables, and to identify how the fields have been defined (as class or instance members, variables or constants). Again, prefixing is used.

Definition typePrefixExample
Member variablesm_m_sName
Static variabless_s_hostsList

It is also possible to distinguish between static variables and constants. Constants are static final variables of immutable types (or possibly are unmodifiable at runtime, as can be created with the Collections.unmodifiable* series of static methods). Constants are also fully created at static initialization time. Variables meeting all of these requirements should be named with all uppercase letters, numbers, and underscores, e.g. ROOT_ELEMENT_NAME

A common alternative approach is to qualify the usage of all member variables with this., and all static variables with the class name. These are more verbose, and further can be violated with a single exception to the convention, as opposed to the variable naming convention which requires all occurrences of the variable name to be consistent. Additionally, prefixing relieves the developer from the problem of resolving collisions between parameters or local variables and field variables. Such name collision should be avoided, as it leads to programmer confusion, is often a source of bugs, and decreases the readability of the code.

Other variable and method naming considerations

Underscores (_) should not be used in variable, method, class, or package names, with only the exception of constants. This is described by Sun's conventions.

Newlines: Braces

Braces should always be used within blocks of code, even if one or no lines of code are contained within that block (e.g. within if, else, for, while, do...while, catch, finally, etc.). Also, braces should always appear on their own line. This applies to both opening and closing braces, in all usages. For example:
if( bDoIt )
{
    // Do some stuff...
}
else
{
    // Don't do anything...
}
This approach comes at the expense of vertical space, however it visually groups blocks of related code, making it clear and obvious to the programmer where the boundaries of that block of code are. This can be obscured if the opening clause spans multiple lines, or if the location of the opening brace is not visually. For example, consider the following comparison:
if( bAlive && someObject.checkTheString(sName.substring(start, end) &&
    anotherObject.testThisThing(thing) ) {
    anotherObject.process(thing);
}
versus:
if( bAlive && someObject.checkTheString(sName.substring(start, end) &&
    anotherObject.testThisThing(thing) )
{
    anotherObject.process(thing);
}
In the first example, it is less clear at a glance whether the call to process is within the if or not. It requires the programmer to scan each line following the if to find the curly brace. In contrast, in the second example the programmer does not need to look beyond the first column to know where the if block begins.

Newlines: Throws

The throws portion of a method declaration should always appear indented on its own line, rather than at the end of the line with method name and argument list. For example consider the following comparison:
protected void create( String sClassName, Configuration config, URL urlParam ) throws InstantiationException, 
    IllegalAccessException, IllegalArgumentException, InvocationTargetException
{
    ...
}
versus:
protected void create( String sClassName, Configuration config, URL urlParam )
    throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException
{
    ...
}
Now, just for fun, let's replay this example incorporating variations on the other things we've discussed:
protected void create(String className, Configuration config, URL param) throws InstantiationException, 
    IllegalAccessException, IllegalArgumentException, InvocationTargetException {
    Class realClass = Class.forName(className);
    ...
}
versus:
protected void create( String sClass, Configuration config, URL urlParam )
    throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException
{
    Class class = Class.forName(sClass);
    ...
}

Spaces

A tab stop of 4 should be used, and the tab character should be avoided (for reasons explained in The Elements of Java Style).

In order to separate an argument from the method call, or clause from its operator, a space should always appear after a left parenthesis and before a right parenthesis. Additionally, no space should be before the left parenthesis, or after the right parenthesis, e.g. String.valueOf( fNumber ).indexOf( "1415" );

The exception to this is when casting. Here the close paren is adjacent to the object being cast, e.g. (String)iter.next().

Binary operators should have a space on either side of the operator, e.g. nCount = nLost + nFound;, whereas unary operators should not, e.g. nCount++;

Whitespace should never appear on either side of a period (.). If a line is too long and needs to be broken up, a more appropriate place to break the line is within parentheses.

Class layout

While the Sun recommends an order for class and interface declarations, this guideline does not draw a distinction between class and instance methods, factory methods and static methods, nor does it specify the order for the static initializer or inner classes. We propose an ordering that includes these explicitly, and is specifically oriented for consumers of the class. Specifically, Sun's ordering places fields at the top of the class. These are implementation details of the class, and should be less relevant to its consumers, hence closer to the bottom. Factories, constructors, and methods, however, are more salient to consumers, and hence are at the top of the class. Within each section, the declarations should be in order of increasing protection (consistent with Sun's recommendation). Our recommended order is:
  1. Constructors
  2. Factory methods
  3. Instance methods
  4. Static methods
  5. Inner classes
  6. Instance variables
  7. Static variables
  8. Constants
  9. Static initializers
Each item in this list should have a descriptive Javadoc comment above it.

Reasoning

Style is subjective, and there are many fair arguments for the styles proposed here, as well as their alternatives. I encourage the reader to adopt a style that appeals to them from an aesthetic and stylistic point of view. When working on a team it is also important to select style guidelines that offer sufficient guidance, so that a consistent code base can be attained.

Consistent style is a necessary, but by no means sufficient, criterion for a high quality code base. New software engineers will find that by obeying style guidelines, they impart their code with structure and credibility that can be used as a springboard to develop skill and experience. More experienced engineers will understand the importance of consistency in the code they deal with, and recognize the direct relationship between product quality and code quality.

Tools

The Checkstyle tool can be used to enforce coding conventions at build time (or development time with the Eclipse Checkstyle Plug-in). A Checkstyle configuration that encapsulates some of the ideas described here, along with some additional conventions that should be obeyed is available here.

References

  1. Seven Pillars of Pretty Code
    Christopher Seiwald
    Perforce

  2. Hungarian Notation
    Charles Simonyi

  3. Code Conventions for the Java Programming Language
    Sun Microsystems, Inc.

  4. The Elements of Java Style
    Vermeulen, et al.
    Cambridge University Press, 2000

  5. Making Wrong Code Look Wrong
    Joel Spolsky