Java Language Coding Guidelines

Introduction

This coding style guide is a simplified version of one that has been used with good success both in industrial practice and for college courses.

This has been taken, with permission, from Cay Horstmann, Big Java 3e, John Wiley and Sons, 2008, and modified to meet the standards adopted by the University of South Carolina.

A style guide is a set of mandatory requirements for layout and formatting. Uniform style makes it easier for you to read code from your instructor and classmates. You will really appreciate that if you do a team project. It is also easier for your instructor and your grader to grasp the essence of your programs quickly

The primary source of error in writing programs, especially by those who are new to the game, is that people get sloppy, skip steps, and inadvertently shoot themselves in one or both feet. By following a guideline like this and making these precepts into habits, you become less likely to make the common errors to which we are all prone.

A style guide also makes you a more productive programmer because it reduces gratuitous choice. If you don't have to make choices about trivial matters, you can spend your energy on the solution of real problems.

Current practice at the University of South Carolina is that Eclipse is used as the IDE for CSCE 145 and 146. Many, but not all, of these standards are to accept as standard that which Eclipse does by default. This will help you to follow the standard, because we will not ask you to something different from the Eclipse standard. When instance variables are created, for example, Eclipse will (if you have this option set) create templates for accessors and mutators for the instance variables. We are insisting that you follow this format as the standard.

In these guidelines, several constructs are plainly outlawed. That doesn't mean that programmers using them are evil or incompetent. It does mean that the constructs are not essential and can be expressed just as well or even better with other language constructs.

If you already have programming experience, in Java or another language, you may be initially uncomfortable at giving up some fond habits. However, it is a sign of professionalism to set aside personal preferences in minor matters and to compromise for the benefit of your group.

These guidelines are necessarily somewhat dull. They also mention features that you may not yet have seen in class. Here are the most important highlights:

To every rule there is an exception, and therefore we make allowance for the possibility that you will need to violate these rules. If you need to violate these rules, you MUST include a comment at the point of violation that explains why this violation is essential and why no code that meets the standards would be workable. If you do this, then you must accept the possibility that the instructor or grader will take points off because there was in fact a way to solve the problem without violating the standards.

Source Files

Each Java program is a collection of one or more source files. The executable program is obtained by compiling these files. Organize the material in each file as follows:

The comment explaining the purpose of this file should be in the format recognized by the javadoc utility. Start with a /**, and use the @author and @version tags:

 
/**
COPYRIGHT (C) 1997 Harry Hacker. All Rights Reserved.
Classes to manipulate widgets.
Solves CS101 homework assignment #3
@author Harry Hacker
@version 1.01 2005-02-15
*/

You may if you wish use a more visible form of commenting, still in a mode acceptable to javadoc, but that makes methods easier to spot:

 
/************************************************************
COPYRIGHT (C) 1997 J. Random Student. All Rights Reserved.
Classes to manipulate widgets.
Solves CS101 homework assignment #3
@author J. Random Student
@version 1.01 2005-02-15
*/

Your comments must, however, follow two rules: They must be present in a manner acceptable to javadoc, and they must occur in a uniform style that is at most only slightly different from these two given here.

Classes

Each class should be preceded by a class comment explaining the purpose of the class.

Eclipse will normally expect the order of presentation to be as follows.

  1. Instance variables
  2. Constructors, with the default constructor first
  3. Accessors and mutators, in the order of the instance variables
  4. Other methods

The purpose of this ordering is to make it easy for you, the instructor, and anyone else to look at the code and find the methods. We might also suggest a meaningful ordering of the "other methods" (perhaps alphabetical by method name) to assist in locating methods.

Leave a blank line after every method.

All non-final variables must be private. (However, instance variables of a private inner class may be public.) Methods and final variables can be either public or private, as appropriate.

All features must be tagged public or private. Do not use the default visibility (that is, package visibility) or the protected attribute. IF YOU MUST USE A protected VARIABLE, YOU MUST ALSO INCLUDE A COMMENT AS TO WHY THIS IS ESSENTIAL AND WHY NEITHER PUBLIC NOR PRIVATE WILL WORK PROPERLY TO SOLVE THE PROBLEM.

Avoid static variables (except final ones) whenever possible. In the rare instance that you need static variables, you are permitted one static variable per class.

Methods

Every method (except for main) starts with a comment in javadoc format.

 
/**
Convert calendar date into Julian day.
Note: This algorithm is from Press et al., Numerical Recipes
in C, 2nd ed., Cambridge University Press, 1992
@param day day of the date to be converted
@param month month of the date to be converted
@param year year of the date to be converted
@return the Julian day number that begins at noon of the
given calendar date.
*/
public static int dat2jul(int day, int month, int year)
{
. . .
}

Methods must have at most 30 lines of code. The method signature, comments, blank lines, and lines containing only braces are not included in this count. This rule forces you to break up complex computations into separate methods.

Variables and Constants

Define all variables at the beginning of a block:

 
{  
double xold;
double xnew;
boolean more;
. . .
}

Do not define each variable just before it is used for the first time, except for iteration control variables used only in a for or while loop. By grouping variable definitions together (instance variables whose scope is the entire class at the top of the class block, variables local to a method immediately after the method definition, etc., it will be easier to determine what variables are defined where.

Group definitions of the same type together, and group definitions of primitive types together. These rules are to ease the debugging process. If you are getting errors with a particular variable, you will want to have it easy to determine where the variable is defined and what its type and scope are.

Do not define two variables on the same line:

 
int dimes = 0, nickels = 0; // Don't do this

Instead, use two separate definitions

 
int dimes = 0; // OK
int nickels = 0;

In Java, constants must be defined with the keyword final. If the constant is used by multiple methods, declare it as static final. It is a good idea to define static final variables as private if no other class has an interest in them.

Do not use magic numbers! A magic number is a numeric constant embedded in code, without a constant definition. Any number except -1, 0, 1, and 2 is considered magic:

 
if (p.getX() < 300) // Don't do this

Use final variables instead:

 
final double WINDOW_WIDTH = 300;
. . .
if (p.getX() < WINDOW_WIDTH) // OK

Even the most reasonable cosmic constant is going to change one day. You think there are 365 days per year? Your customers on Mars are going to be pretty unhappy about your silly prejudice. Make a constant

 
public static final int DAYS_PER_YEAR = 365;

so that you can easily produce a Martian version without trying to find all the 365s, 364s, 366s, 367s, and so on, in your code.

Group all the final constants together and immediately before the variable definitions. This way, you will be able immediately to find the constants that are being used if you need to change them or if debugging is necessary.

When declaring array variables, group the [] with the type, not the variable.

 
int[] values; // OK
int values[]; // Ugh--this is an ugly holdover from C

When using collections, use type parameters and not  raw  types.

 
ArrayList<String> names = new ArrayList<String>(); // OK 
ArrayList names = new ArrayList(); // Not OK

Control Flow

The if Statement

Avoid the "if ... if ... else" trap. The code

 
if ( ... )
if ( ... ) ...;
else ...;

will not do what the indentation level suggests, and it can take hours to find such a bug. Always use an extra pair of { ... } when dealing with "if ... if ... else":

 
if ( ... )
{
if ( ... ) ...;
} // {...} are necessary
else ...;

if ( ... )
{
if ( ... ) ...;
else ...;
} // {...} not necessary, but they keep you out of trouble

The for Statement

Use for loops only when a variable runs from somewhere to somewhere with some constant increment/decrement:

 
for (int i = 0; i < a.length; i++)
System.out.println(a[i]);

Or, even better, use the "for each" loop:

 
for (int e : a) 
System.out.println(e);

Do not use the for loop for weird constructs such as

 
for (a = a / 2; count < ITERATIONS; System.out.println(xnew))
// Don't

Make such a loop into a while loop. That way, the sequence of instructions is much clearer.

 
a = a / 2;
while (count < ITERATIONS) // OK
{ . . .
System.out.println(xnew);
}

Here and elsewhere, remember the maxim: Make it right before you make it better. Clear, clean, code that works correctly but uses a naive and puerile programming style is of infinitely greater value than code written to utilize in a single line all the features of a programming language but which fails to execute correctly.


Nonlinear Control Flow

Avoid the switch statement, because it is easy to fall through accidentally to an unwanted case. Use if/else instead.

Avoid the break or continue statements. Use another boolean variable to control the execution flow.

If you must use a break or continue statement, then flag that line in the text with a comment so it will be clearly seen that control flow is not linear.

Exceptions

Do not tag a method with an overly general exception specification:

 
Widget readWidget(Reader in)
throws Exception // Bad

Instead, specifically declare any checked exceptions that your method may throw:

 
Widget readWidget(Reader in)
throws IOException, MalformedWidgetException // Good

Do not "squelch" exceptions:

 
try
{
double price = in.readDouble();
}
catch (Exception e)
{} // Bad

Beginners often make this mistake "to keep the compiler happy". If the current method is not appropriate for handling the exception, simply use a throws specification and let one of its callers handle it.

Lexical Issues

Naming Convention

The following rules specify when to use upper- and lowercase letters in identifier names.

Names must be reasonably long and descriptive. Use firstPlayer instead of fp. No drppng f vwls. Local variables that are fairly routine can be short (ch, i) as long as they are really just boring holders for an input character, a loop counter, and so on. Also, do not use ctr, c, cntr, cnt, c2 for variables in your method. Surely these variables all have specific purposes and can be named to remind the reader of them (for example, current, next, previous, result, . . .). However, it is customary to use single-letter names, such as T or E for generic types.

Indentation and White Space

Use tab stops every three columns or every two columns, but be consistent. That means you may need to change the tab stop setting in your editor.

Use blank lines freely to separate parts of a method that are logically distinct.

Use blank spaces around binary operators:

 
x1 = (-b - Math.sqrt(b * b - 4 * a * c)) / (2 * a);  // Good

x1=(-b - Math.sqrt( b*b - 4*a*c )) / (2*a);//Perhaps OK

x1=(-b-Math.sqrt(b*b-4*a*c))/(2*a);//Bad

Leave a blank space after (and not before) each comma or semicolon. Do not leave a space before or after a parenthesis or bracket in an expression. Leave spaces around the ( . . . ) part of an if, while, for, or catch statement.

 
if (x == 0) y = 0;

f(a, b[i]);

You may choose to violate the rule about spaces and parentheses in constructs such as the following where the extra space helps to identify grouping:

 
      if ( (x == 0) && (y == 1) )
      

Every line must fit on 80 columns. If you must break a statement, add an indentation level for the continuation:

 
a[n] = ..................................................
+ .................;

Start the indented line with an operator (if possible).

If the condition in an if or while statement must be broken, be sure to brace the body in, even if it consists of only one statement:

 
if ( .........................................................
&& ..................
|| .......... )
{
. . .
}

If it weren't for the braces, it would be hard to separate the continuation of the condition visually from the statement to be executed.

Be aware that when you have to break lines, it may well happen that the normal tab stops will not normally allow you to align the second and subsequent lines with the first line. Some will argue that this is a good reason to use blank spaces rather than tabs.

Braces

Two, and only two, options are permissible for braces defining blocks of code.

  1. Opening and closing braces can line up, either horizontally or vertically:

     
    while (i < n) { System.out.println(a[i]); i++; }

    while (i < n)
    {
    System.out.println(a[i]);
    i++;
    }
  2. Or then can follow the pattern that is the default for Eclipse:

     
    while (i < n) { // DON'T
    System.out.println(a[i]);
    i++;
    }

Unstable Layout

Some programmers take great pride in lining up certain columns in their code:

 
firstRecord = other.firstRecord;
lastRecord = other.lastRecord;
cutoff = other.cutoff;

This is undeniably neat, but the layout is not stable under change. A new variable name that is longer than the preallotted number of columns requires that you move all entries around:

 
firstRecord = other.firstRecord;
lastRecord = other.lastRecord;
cutoff = other.cutoff;
marginalFudgeFactor = other.marginalFudgeFactor;

This is just the kind of trap that makes you decide to use a short variable name like mff instead. Use a simple layout that is easy to maintain as your programs change.