Java Style Guide

For Internal Documentation


Introduction

This document offers a uniform style for creating Java source code and documentation, and is intended as a guide for all programming assignments. Adherence to a consistent programming style is beneficial in:

Equivalent documents: Pascal Style Guide and Ada Style Guide, describe a preferred coding style in terms of the language constructs of those languages. The Java Style Guide essentially reuses the Ada Style Guide, translating Ada language references into Java. Although even a brief summary of Java terminology is beyond the scope of this document, the following is an alphabetized description of key Java terms that are either absent from Ada, or that mean different things in Ada than they do in Java. The glossary is intended for those readers already proficient in Ada, and offers a preponderance of explanations from Java's point of view.
class In Java, a collection of data and methods that operate on that data. These components are the fields that comprise the class. Each file of Java source code defines (specifies the workings of) one or more, differently named classes. The only other text in a Java source file that is not part of a class definition, is leading package and import statements (see there), and comments. During program execution the JVM (Java Virtual Machine) creates distinct "instances" of a class. A created instance of a class is exactly equivalent of the object oriented concept of object.
comment Java comments are three types:
/* comment text */ -- as in C; may span multiple lines; cannot be nested
/** comment text */ -- version of the above, for the javadoc document generator
// comment text -- like Ada's "--"; the comment lasts until the end of the line
constant Any variable declared in Java using the "final" keyword must also be initialized in the same declaration, and its value is immutable. The conventional idea of a constant is most closely implemented by declaring the variable "static final", causing the only copy of the variable to be associated with the "boiler plate" definition of the enclosing class, rather than with different instances of the class (which would be the case had the variable been declared without the "static" keyword).
garbage collection Java has automatic run-time garbage collection: any object or array no longer referenced from that point on, in the executing program, is automatically deallocated by a clean-up thread running in parallel.
import In Java, this statement enables the source file in which it appears, to refer to classes specified in different packages by their class name alone (without having to prepend the package name to the class name -- see name space and package). While this means having to type less when creating the source code, the absence of information as to the origin of the referenced classes, can make the code more difficult to follow.
main function Unlike in conventional languages where functions have a life of their own, Java methods (functions) can exist only as component members (fields) of classes. Still, of the group of classes comprising the application, one class must define a main() method, and the application starts running in this method. (Applets, in contrast to applications, do not have a main() method; they depend instead on the browser or appletviewer program in whose context they execute, to have one.) Apart from the unusual case where the application just wants to print strings to the system console, the main() method simply instantiates (creates an object of) the class in which it was defined; this in turn transfers control to the constructor method of the newly created class, and out of main(). A consequence of this kind of bootstrapping is that the definition of the main() method is hardly ever longer than a few lines, not warranting the special attention it receives in the Ada Style Guide.
On the other side of this issue, while one class must define main(), any and all classes of an application can define main(). Of the various different main() methods defined by different classes of an application, the only main() that actually executes, is the main() in which the application started running. This means that any class definition can implement its own unit-test program as main(). The test functionality will then always be enabled, and can be executed stand-alone with
java classname.
name space At the root of Java's "container hierarchy" is the package; all Java software on a given computer is separated into various packages. Each package is a collection of classes. Each class is a collection of fields: variables and methods. There are no global variables in the conventional sense, and there are no global methods. Each variable or method may be referred to by its fully qualified name: the package name, the class name and the field name, separated by periods. The source code may allow visibility of its classes and class fields (external access from other source code, to its data structures) on a per-class or per-field basis, from public (most visible) to private protected (least visible), with seemingly too many grades in-between. On the other hand, variables declared inside method definitions are strictly local and may not be referred to from outside of the method.
object One of three Java data types (the other two are primitives and arrays). The primitives are: boolean, char, byte, short, int, long, float, double. Since pointers are absent from Java, primitives can only be accessed by their variable name, and are always passed into methods (via the parameter list), by value. In contrast, more than one variable may refer to a particular object, or to a given array. Objects and arrays are always handled by reference. Objects can only be created dynamically, with the new operator. Objects are instances of a class.
Object (With a capital 'O') is the root class in Java. Each class inherits the methods of Object.
package The root (leftmost) component of every fully qualified name in Java (see also: name space), the package name itself can be a period- separated list of components corresponding to an existing path on the system leading to the directory that contains the class definitions comprising the package. The package statement is optional text in a class definition file (but it must appear as the first non-white-space or non-comment text in the file), explicitly establishing common group membership of the class or classes defined in the directory that contains the source file.
reserved words Java's reserved word syntax (keywords, type identifiers, and in fact all Java text) is case sensitive. Whereas in Ada one may declare "procedure X" and "PROCEDURE x" equivalently, Java's reserved words are all lower case, and are not understood otherwise.
signature In Java, that part of the class or method definition that precedes the left curly brace { delimiting the beginning of the elaboration of the class fields, or of the declarations of variables and statements of the method. Method signatures differ from C++ prototypes only by the absence of a terminating semicolon. Prototypes are unnecessary in Java, since both the compiler and the interpreter locates methods and all other data types by their fully qualified name (see import, package). On the other hand, the absence of an Ada-like "specification" file leaves a third-party programmer utilizing existing classes, without interface specifications mandated by the language. This is why commenting Java source code in the syntax understood by javadoc is essential: javadoc automatically generates the API (Application Programming Interface) in HTML format.
type Java does not support an equivalent of the Ada type keyword for defining data types. There are only three data types: objects (instances of classes), arrays, and primitives. The primitive (or scalar) types are: boolean, char, byte, short, int, long, float, double. The user constructs new data types by defining new classes.

Program structure and units

  1. All variables should be declared near to where they are deployed. Variables that recur in different sections of a method or class definition, should be declared immediately after the signature of the method or class, rather than where the program manipulates them for the first time.
  2. For most programs, the definition of a method should fit on a single (printed) page.
  3. Except for "clean-up" code specifically written for exception handling, there should be only one return statement per method definition.
  4. When defining classes, class fields (variables and methods) should be grouped into categories that reflect the internal organization of the class. The categories should be in the following order:
    1. Constants
    2. Class (static) variables
    3. Public instance variables
    4. Protected instance variables
    5. Public constructors
    6. Protected constructors
    7. Class (static) methods
    8. Public instance methods
    9. Protected instance methods
  5. Since Java does not require, nor supports, "interface specifications" or "prototype files", a disciplined effort should be made to comment all source code components understood by javadoc with /** . . . */ type comments. See the Comments section of this Guide for details.

Identifiers

  1. Literals (digit strings representing numbers) should not be "hard coded"; they should be represented by constants instead. Constant names should contain upper case letters, digits and the underscore character only. Examples:
  2.         public static final double PI = 3.14159;
            static final int WIDTH_OFFSET = 33;
  3. Every word in a class name should begin with a capital letter; the remaining letters should be lower case. Examples:
  4.         class QueryPersonalDatabase extends Panel {. . .}
            public class java.awt.CheckboxMenuItem
                 extends java.awt.MenuItem {. . .}
  5. The first word of field names and method parameter names should be lower case throughout; the remaining words should all begin with a capital letter, except for abbreviations, which should be upper case. Examples:
  6.         boolean  isEOF;
            void solvePuzzle (int squarePeg, int roundHole) {
  7. Class and variable names should be nouns. Method (function) names should be verbs. Examples:
  8.         class GiantStep;
            void stepAhead (int stepCount) {
  9. Identifiers should be chosen to be descriptive and intuitive for an outsider reading the code, rather than just a convenient mnemonic shorthand for the author. Example:
  10.         topLeftCorner
    rather than
            xy0

Indentation, Alignment and Spacing

  1. Consistent indentation should be maintained throughout, using a fixed number of spaces to indent each successive level of nesting within the program. The TAB character may be put to good use instead of spaces, especially if the logic is not deeply nested. Example:
  2.         if (countInstalled < ALLPIECES) {
                    int nextSquarePeg = squarePeg;
                    while (boardArray[nextSquarePeg] != 0)
                            nextSquarePeg++;
                    solvePuzzle(nextSuarePeg, roundHole);
            }
  3. Loop control statements and test statements should appear in their own line, above the statements they control. Example:
  4.         if (overTheSpeedLimit)
                    easeOffGas();
            else if (road == gardenStateParkway)
                while (speed < MINIMUM_SPEED)
                    stepOnGas();
    rather than
            if (overTheSpeedLimit) easeOffGas();
            else if (road == gardenStateParkway)
                while (speed < MINIMUM_SPEED) stepOnGas();
  5. Each statement should be on a separate line. Example:
  6.         array_Index = 0;
            flag = FALSE;

    rather than

            array_Index = 0; flag = FALSE;
  7. Each variable declaration should be on a separate line, except for comma-separated variable initializers in for-loops. Each private declaration should be followed with an in-line comment documenting its function. (Non-private declarations should immediately follow a /** . . . */ type javadoc comment.) Example:
  8. 
            private static final int ALLPIECES = 16; // checkers constant
            private MyBoardCanvas boardCanvas;       // board display class
            private int squareClicked;               // where to move next
            private boolean oneStepOnly;             // no jump possible
  9. Binary operators should be surrounded by blanks. Unary operators should directly precede their operands. Examples:
  10.         netPay = grossPay - stateTax - federalTax;
            amountOwed = -totalDebits;
  11. Each condition of an if() ... else if() ... else() test sequence, as well as all "case" and "default" labels of a "switch" statement, should be at the same level of indentation. Example:
  12.         if (oneStepOnly)
                    oneStepOnly = false;
            else if (thisOneIsDown[piece[p][0]] == false) {
                    thisOneIsDown[piece[p][0]] = true;
                    countInstalled++;
            }
            else {
                    stepButton.enable();
                    goButton.enable();
                    pauseButton.disable();
            }
  13. Of the two Lilliputian factions -- one camp putting the left curly brace { at the end of the header line before a new text block, the other camp putting the left curly brace in the line below -- the author of this Guide sides with the former. More to the point, one should make a choice and then use the chosen style consistently.

Comments

  1. Comments improve comprehension throughout a program. Comments should be added to describe relatively long sets of related statements, algorithms that are not completely obvious, and any logical structure or group of statements that require special attention.
  2. In-line comments, to the right of a list of declarations, should line up.
  3. Right curly braces } terminating code blocks which themselves contain nested right curly braces (including those that terminate method or class definitions) should each be followed by an in-line comment denoting the text block which the closing brace terminated. Example:
  4.         public void run() {
                    setBackground(Color.blue);
                    while (true) {
                            for (xPos = 5; xPos <= 105; xPos += 4) {
                                    . . .
                                    try {
                                            Thread.sleep(100);
                                    }
                                    catch (InterruptedException e) {}
                                    . . .
                            } // end of xPos for-loop
                            . . .
                    } // end of infinite while
            } // end of the run() method
  5. Debug statements may be left in code to assist future software maintenance, by the simple expedient of commenting out the debug statements before releasing the software. Note however, that Java's C-style comments may not be nested, so commenting out debug statements may be difficult if the debug statements themselves were initially commented using C-style comments. It may be better to define a "debug constant" during development, as
  6.         static final boolean DEBUG = true;

    and add debug statements inside

                if (DEBUG) { . . . }

    blocks. Then to disable the debug statements, the debug constant can be redefined as

            static final boolean DEBUG = false;

    causing the if (DEBUG) { . . . } block to be skipped during normal operation.

  7. Non-public class definitions should each have a relatively verbose comment before the class signature, explaining the purpose of the class. Example:
  8. 
        /* MyForm is the superclass for all personal data
           entry forms used in the database, ensuring that all
           forms filled in by the user interactively, have a
           consistent look and feel. */
        class MyForm extends Frame { . . . }
  9. In Java, each public class must be defined in a separate text file named identically as the class defined therein, followed by the ".java" extension. If more classes (than just the public class) are defined in a file, the public class should be the first class defined in the file.
  10. Since Java does not require, nor supports, "interface specifications" or "prototype files", a disciplined effort should be made to comment all source code components understood by javadoc with /** . . . */ type comments. Javadoc recognizes A comment should be placed immediately above the definition it refers to. Comments may contain HTML tags except header tags (<H1>, <H2>, and so on). Comments may end with a list of text lines, each line beginning with a javadoc tag, from the set:
        @see @version @author @param @return @exception
    (The @ character must either be the first byte of such lines, or each successive line of the comment must begin with *.) The command
        javadoc *.java
    generates a set of HTML files in the current directory. These HTML files embody the API (Application Programming Interface) of the listed .java source files. (The HTML files depend on approximately 25 small GIF files in the subdirectory images -- part of Sun's HTML Java API distribution -- for formatting bullets and titles. The following example is the first part of an actual Java class definition, containing javadoc comments for the public class and for the first two constructor methods:
  11. import java.awt.*;
    
    /**
      <P>This class defines the internal states  of Spider objects.
       The class name refers to Feldman's "Spider graphics" programs
       developed in the textbook "Ada 95".  Spiders are instantiated in the
       graphic environment realized by objects of class Room: they move around
       in a room, leaving a colored "silk" trail and small icons of themselves.
       The color of the silk trail can be changed under program control.
       The spider icon is shaped like a letter M, with a small circle for
       the spider's belly at the point where the slanted inner lines meet.
       The four lines that represent the (front) legs of the spider are always
       in the foreground color (black), the belly color can be set with some
       of the Spider constructor methods but cannot be changed thereafter.
       Spiders have no useful life by themselves (outside of a Room).
    
      <P>Spiders in this implementation are very simple creatures:
       they retain information but do not do anything on their own.  All
       graphics operations for spiders are defined as methods of Room;
       these Room methods take a Spider object as their first argument.
       Spider methods are limited to mutator or accessor roles:
       mutator methods allow write access to the private Spider states,
       whereas accessor methods allow read access of these variables.
    
      <P>A more comprehensive implementation of the Spider class would give
       Spider objects feedback from Room, allowing the development of spider
       behavior based on that feedback.
    
    @author Michael B. Feldman, The George Washington University (Ada 95)
    @author Istvan Mohos (Java translation)
    @see AppFrame
    @see Room
    */
    class Spider {
    
      /* Spider internal states; these can be accessed by client objects only
         through accessor (get...) and mutator (set...) methods.
      */
      private int currentX;                 // horizontal position, pixels
      private int currentY;                 // vertical position, pixels
      private int heading;                  // spider's direction
      private Color ink;                    // current drawing color
      private Color bellyColor = Color.red; // fixed at instantiation
    
      /** Creates a red-bellied
         spider initially drawing green "silk", targeted for the origin (0, 0)
         of the drawing surface, facing NORTH (constant defined in Room, meaning
         vertically up on the screen).
      */
      public Spider() {
        this.setSilk(Color.green);
      }
    
      /**
        Places a new spider at the X, Y coordinates specified by the first two
        parameters, headed in the direction specified by the third parameter,
        drawing "silk" in the color specified by the fourth parameter, and
        with its belly color specified by the final parameter.
    @param startX the X ordinate (in pixels) of the spider's position in
        the Room (no bounds checking is performed by this constructor).
    @param startY the Y ordinate (in pixels) of the spider's position in
        the Room (no bounds checking is performed by this constructor).
    @param heading one of: Room.NORTH, Room.EAST, Room.SOUTH, Room.WEST.
        Out of range values are silently converted by taking the absolute
        modulo_4 of the input.
        A spider headed Room.NORTH is oriented upright (like the letter M) and
        would move toward the top of the screen.  A spider headed Room.SOUTH
        is drawn like the letter W, and would move toward the bottom of the
        screen. A spider headed Room.WEST looks like a letter M turned on
        its left side, and would move toward the left.
        A spider headed EAST looks like a letter M turned on its right side,
        and would move toward the right.
    @param ink the Color of the spider's "silk"; may change thereafter.
    @param bellyColor the Color of the spider's belly; cannot change
        thereafter.
      */
      public Spider(int startX, int startY, int heading,
                    Color ink, Color bellyColor) {
        currentX = startX;
        currentY = startY;
        this.heading = Math.abs(heading) % 4;
        this.ink = ink;
        this.bellyColor = bellyColor;
      }
    
      . . .