Adapted with permission from JAVA CODE CONVENTIONS. Copyright 1995-1999 Sun Microsysytems, Inc. All rights reserved.
http://java.sun.com/docs/codeconv/
|
http://student2.cs.appstate.edu/classes/JavaCodingStyle/cs_appstate_checks.xml
There is a plug-in for the Eclipse development environment. Info can be found at http://eclipse-cs.sourceforge.net/ project site. This site explains how to install the plug-in.
Now you need to tell the plugin to check according to our style conventions. Below are some instructions for the Helios version of Eclipse. The Juno version has some of these steps in the Project > Checkstyle > Properties area described below and some steps are in the main Eclipse Properties window.
http://student2.cs.appstate.edu/classes/JavaCodingStyle/cs_appstate_checks.xml
Once installed, you need to enable checking project-by-project. Highlight your project name and right-click (Macs: Ctrl-click) the project name. Select Properties from this menu. Select Checkstyle in the left-side panel of the Properties window. Check the box to enable checking. (Notice you can change the check configuration file here too.)
[BACK TO TOP]There is a Unix command-line tool available. It is located in /usr/local/bin/checkstyle, but you should be able to simply say: checkstyle to run it.
Here are a couple of examples of usage:
% checkstyle Blah.java % checkstyle *.java % checkstyle *.java > checker.log
The last usage example redirects the checker output to the file checker.log which you can then print, email, view in an editor, etc.
[BACK TO TOP]There is an online web-based checker located at:
http://euler.acadiau.ca/~giles/checkstyle/
Note that this checker does NOT check according to OUR style conventions. We hope to have a web-based version soon. Check back....
[BACK TO TOP]Files longer than 1000 lines are cumbersome and should be avoided.
Each Java source file contains a single public class or interface. When private classes and interfaces are associated with a public class, you can put them in the same source file as the public class. The public class should be the first class or interface in the file.
Java source files have the following ordering:
package
and import
statements
package
statement is optional
class
or interface
statement.extends
and implements
clauses.
static
) variables.public
class variables, then the protected
, then package level (no access modifier), and then the private
.
public
, then protected
, then package level (no access modifier), and then private
.
This is often the starting point when exploring directories of source code. As such, it often describes the overall project, design decisions, limitations, exceptional features, etc.
This file should describe how to build the project and how to run the project.
[BACK TO TOP]Four spaces should be used as the unit of indentation. Tabs should be converted to spaces.
[BACK TO TOP]
Avoid lines longer than 80 characters, since they're not handled well by many terminals and tools.
NOTE: See section 10 for ways to break long lines.
When an expression will not fit on a single line, break it according to these general principles:
Here are some examples of breaking method calls:
someMethod(longExpression1, longExpression2, longExpression3, longExpression4, longExpression5); var = someMethod1(longExpression1, someMethod2(longExpression2, longExpression3));
Following are two examples of breaking an arithmetic expression. The first is preferred, since the break occurs outside the parenthesized expression, which is at a higher level.
longName1 = longName2 * (longName3 + longName4 - longName5) + 4 * longname6; // PREFER longName1 = longName2 * (longName3 + longName4 - longName5) + 4 * longname6; // AVOID
Following are two examples of indenting method declarations. The first is the conventional case. The second would shift the second and third lines to the far right if it used conventional indentation, so instead it indents only 8 spaces.
Line wrapping for//CONVENTIONAL INDENTATION someMethod(int anArg, Object anotherArg, String yetAnotherArg, Object andStillAnother) { ... } //INDENT 8 SPACES TO AVOID VERY DEEP INDENTS private static synchronized horkingLongMethodName(int anArg, Object anotherArg, String yetAnotherArg, Object andStillAnother) { ... }
if
statements should generally use the 8-space rule, since conventional (4 space) indentation makes seeing the body difficult. For example:
[BACK TO TOP]//DON'T USE THIS INDENTATION if ((condition1 && condition2) || (condition3 && condition4) ||!(condition5 && condition6)) { //BAD WRAPS doSomethingAboutIt(); //MAKE THIS LINE EASY TO MISS } //USE THIS INDENTATION INSTEAD if ((condition1 && condition2) || (condition3 && condition4) ||!(condition5 && condition6)) { doSomethingAboutIt(); } //OR USE THIS if ((condition1 && condition2) || (condition3 && condition4) ||!(condition5 && condition6)) { doSomethingAboutIt(); }
Java programs can have two kinds of comments: implementation comments and documentation comments. Implementation comments are those found in C++, which are delimited by /*...*/, and //. Documentation comments (known as "doc comments") are Java-only, and are delimited by /**...*/. Doc comments can be extracted to HTML files using the javadoc tool.
Implementation comments are meant for commenting out code or for comments about the particular implementation. Doc comments are meant to describe the specification of the code, from an implementation-free perspective, to be read by developers who might not necessarily have the source code at hand.
Comments should be used to give overviews of code and provide additional information that is not readily available in the code itself. Comments should contain only information that is relevant to reading and understanding the program. For example, information about how the corresponding package is built or in what directory it resides should not be included as a comment.
Discussion of nontrivial or nonobvious design decisions is appropriate, but avoid duplicating information that is present in (and clear from) the code. It is too easy for redundant comments to get out of date. In general, avoid any comments that are likely to get out of date as the code evolves.
Note:The frequency of comments sometimes reflects poor quality of code. When you feel compelled to add a comment, consider rewriting the code to make it clearer.
Comments should not be enclosed in large boxes drawn with asterisks or other characters.
Comments should never include special characters such as form-feed and backspace.
Documentation comments are specified using the Javadoc notation.
The first line of a doc comment is "/**", and subsequent lines vertically align the asterisk, and */ ends the comment.
Documentation comments describe entities (files, classes, methods) at a specification level not a programming level.
Documentation comments immediately precede the entity they describe.
For further details, see the following resources:
Optionally, a Java source file may start with a comment. Typical use of such a comment would identify the filename, any copyright information, version and author history, list of classes/interfaces defined within the file, etc.
Since many Java files only define a single class, this file level comment and the class level comment (see below) incorporate the same information. Thus, typically, the file level comment is not required.
[BACK TO TOP]/** * Filename.java * * Optional description of purpose of file/class; for example, to indicate * course and assignment. * * @author Harry Hacker * @version 12/25/2011 * * COPYRIGHT (C) 1997 Harry Hacker. All Rights Reserved. */
[BACK TO TOP]/** * Simple one-line description of class, ending with a period. * * Optional, longer description of purpose of class goes here. This * comment can provide additional details of class design decisions, for * example. Many HTML tags are allowed! * NOTE: @author and @version tags are REQUIRED. * * @author Harry Hacker * @version 12/25/2011 */
Method doc comments should have the one line summary. The longer description is optional. Html formatting can be used to increase readability.
Method doc comments should include separate @param tags for each parameter that have the form: @param name description
Method doc comments should include an @return tag.
[BACK TO TOP]/** * Computes distance in Cartesian plane fromthis
point to the given Point. * * Computation uses a variant of the familiar * Pythagorean Theorem. * * @param p the second Point of the line segment * @return non-negative distance between the two points * or a negative value if the parameter is the same object asthis
*/ public float getDistance(Point p) { ... }
Programs can have various styles of implementation comments: block, single-line, and trailing.
Note:The frequency of comments sometimes reflects poor quality of code. When you feel compelled to add a comment, consider rewriting the code to make it clearer.
[BACK TO TOP]Block comments are used to provide longer descriptions within methods.
Block comments should be indented to the same level as the code they describe.
A block comment should be preceded by a blank line to set it apart from the rest of the code. [BACK TO TOP]Short comments can appear on a single line indented to the level of the code that follows.
Single-line comments can be of either form:
[BACK TO TOP]/* A C-style single-line comment. */ // Another style single-line comment.
Generally, trailing comments should be avoided as they too often get lost in the code. However, if used, they should be shifted far enough to separate them from the statements. If more than one short comment appears in a chunk of code, they should all be indented to the same tab setting.
Note:Notice how changing the code causes the alignment to require change too, leading to poor comment style.
Note:See earlier note about over-commenting.
Here's an example of a trailing comment:
[BACK TO TOP]if (a == 2) { return TRUE; /* special case */ } else { return isPrime(a); // works only for odd a }
Only one declaration per line.
/* This is correct: */ int level = 0; int size = 0; // This is not: int level = 0, size = 0;
Use one space between the type and the identifier, as shown above.
Some programmers like to align declarations, but keeping this formatting becomes a code maintenance problem. (Consider what happens if level variable's type changes to Integer: many other entries must be moved - ugh.)
[BACK TO TOP]// This is bad style: int level; // indentation level int size; // size of table Object currentEntry; // currently selected table entry
Initialize local variables when they are declared.
Note:This can lead to a slight execution inefficiency, but the gains of clarity and portability generally outweigh this consideration.
[BACK TO TOP]Put declarations only at the beginning of blocks. (A block is any code surrounded by curly braces "{" and "}".) Don't wait to declare variables until their first use; it can confuse the unwary programmer and hamper code portability within the scope.
void myMethod() { int int1 = 0; // beginning of method block if (condition) { int int2 = 0; // beginning of "if" block ... } }
Note:This can lead to a slight execution inefficiency, but the gains of clarity and portability generally outweigh this consideration.
The one exception to the placement rule is indexes of for
loops, which in Java can be declared in the for
statement:
for (int i = 0; i < maxLoops; i++) { ... }
Avoid local declarations that "hide" declarations at higher levels. For example, do not declare the same variable name in an inner block:
[BACK TO TOP]int count; ... myMethod() { if (condition) { int count = 0; // AVOID! ... } ... }
When coding Java classes and interfaces, the following formatting rules should be followed:
implements
clauses and exception throws
clauses.
class Sample extends Object { int ivar1; int ivar2; Sample(int i, int j) { ivar1 = i; ivar2 = j; } void emptyBody() {} }
Each line should contain at most one statement. Example:
[BACK TO TOP]argv++; // Correct argc--; // Correct argv++; argc--; // AVOID!
A compound statement (also called a "block") is itself a single statement that contains a sequence of statements enclosed in braces "{ statements }
".
The enclosed statements should be indented one more level than the compound statement (i.e., the braces).
The opening and closing braces should be on their own lines and be indented to the beginning of the compound statement.
Braces are used around all statements, even single statements, when they are part of a control structure, such as a if-else
or for
statement. This makes it easier to add statements without accidentally introducing bugs due to forgetting to add braces.
Blocks should not be left empty.
NOTE:If wanting to "stub out" a method use a valid return statement. Exception "catch" blocks should - at a minimum - call the printStackTrace() method on the exception object.
A return
statement with a value should not use parentheses unless they make the return value more obvious in some way. Example:
[BACK TO TOP]return; return myDisk.size(); return (size ? size : defaultSize);
The if-else
class of statements should have the following form:
if (condition) { statements; } |
A series ofif (condition) { statements; } else if (condition) { statements; } else { statements; } if 's nested inside of else 's should take the more vertical form shown above.
|
if (condition) { statements; } else { statements; } |
Note: if
statements always use braces {}.
A for
statement should have the following form:
[BACK TO TOP]for (initialization; condition; update) { statements; }
A while
statement should have the following form:
[BACK TO TOP]while (condition) { statements; }
A do-while
statement should have the following form:
[BACK TO TOP]do { statements; } while (condition);
A switch
statement should have the following form:
switch (condition) { case ABC: statements; /* falls through */ case DEF: statements; break; case XYZ: statements; break; default: statements; break; }
Every time a case falls through (doesn't include a break
statement), add a comment where the break
statement would normally be. This is shown in the preceding code example with the /* falls through */
comment.
Every switch
statement should include a default case. The break
in the default case is redundant, but it prevents a fall-through error if later another case
is added.
A try-catch
statement should have the following format:
try { statements; } catch (ExceptionClass e) { statements; }
A try-catch
statement may also be followed by finally
, which executes regardless of whether or not the try
block has completed successfully.
[BACK TO TOP]try { statements; } catch (ExceptionClass e) { statements; } finally { statements; }
Blank lines improve readability by setting off sections of code that are logically related.
One blank line should always be used in the following circumstances:
Blank spaces should be used in the following circumstances:
while (true) { ... }
Note that a blank space should not be used between a method name and its opening parenthesis. This helps to distinguish keywords from method calls.
.
should be separated from their operands by spaces. Blank spaces should never separate unary operators such as unary minus, increment ("++"), and decrement ("--") from their operands. Example:
a += c + d; a = (a + b) / (c * d); while (d++ = s++) { n++; } printSize("size is " + foo + "\n");
for
statement should be separated by blank spaces. Example:
for (expr1; expr2; expr3)
Blank spaces should NOT be used in the following circumstances:myMethod((byte) aNum, (Object) x); myMethod((int) (cp + 5), ((int) (i + 3)) + 1);
Naming conventions make programs more understandable by making them easier to read. They can also give information about the function of the identifier; for example, whether it's a constant, package, or class, which can be helpful in understanding the code.
Don't make any instance or class variable public without good reason.
Numerical constants (literals) should not be coded directly, except for -1, 0, and 1, which can appear in a for
loop as counter values.
Use named constants in place of these magic numbers.
[BACK TO TOP]int currMinSpeed = 40; // magic number private static final int DEFAULT_MAX_SPEED = 65; // named constant int currMaxSpeed = DEFAULT_MAX_SPEED;
It is generally a good idea to use parentheses liberally in expressions involving mixed operators to avoid operator precedence problems. Even if the operator precedence seems clear to you, it might not be to others-you shouldn't assume that other programmers know precedence as well as you do.
[BACK TO TOP]if (a == b && c == d) // AVOID! if ((a == b) && (c == d)) // RIGHT
Avoid redundant boolean constant return values
if (booleanExpression) { return true; } else { return false; }
[BACK TO TOP]return booleanExpression;
Code duplication is undesirable for several reasons, including code bloat and maintenance difficulties.
"Procedural abstraction" is the standard solution to code duplication. Abstract the duplicated code into its own method (a.k.a., procedure) and then invoke the procedure instead of duplicating.
Notice that procedure parameters can be used to vary the "duplicate" slightly.
[BACK TO TOP]It is acceptable to break statements onto multiple lines at operators. For example,
aLongishVariableName = anotherSignificantlyLongName + "this is okay" + andSomeOtherStuff;
It is acceptable to break long function call statements at parameters. For example,
[BACK TO TOP]aLongishName = foo.aLongMethodName(parameterOne, parameterTwo, parameterThree, parameterFour);
Below is a sample Java class that demonstrates many of the coding style items described in this document. Here is the result of running javadoc on this file: Greeting.html.
[BACK TO TOP]/** * Greeting.java * * The following classes are defined in this file: * Greeting */ import java.util.Scanner; /** * An obfuscated HelloWorld program to demonstrate coding style. * * A dual-purpose class to (1) play with the classic first program * "Hello World", and (2) demonstrate proper coding styles. Note that * to invoke a large number of style issues, the code is somewhat * (okay, largely :) obfuscation. * * @author Jay Fenwick * @version Dec 2011 */ public class Greeting { private static final String DEFAULT_INTRO = "Hello"; private String user; private Scanner keyboard; /** * Parameterless constructor, initializes keyboard input. */ public Greeting() { keyboard = new Scanner(System.in); } /** * Alternate constructor. * * @param u user of the program */ public Greeting(String u) { /* Notice this nifty way to initilize the keyboard Scanner WITHOUT duplicating code by invoking the other constructor. */ this(); user = u; } /** * Builds a greeting. * * Uses Scanner object to get input from keyboard for customization. * * @param introduction customized greeting intro * @return a customized greeting */ private String make(String introduction) { String greeting = "Hello"; if (introduction != null) { greeting = introduction; } // Customize with user's name! if (user == null) { System.out.print("Please enter your name: "); user = keyboard.nextLine(); } greeting = greeting + ", " + user + "."; return greeting; } /** * Says default greeting. */ public void say() { /* Notice the nifty way to use overloaded method to avoid code duplication! */ say(DEFAULT_INTRO); } /** * Says the greeting. * * Uses private internal method to customize. * * @param intro customized greeting intro */ public void say(String intro) { String greeting = make(intro); System.out.println(greeting); } /** * Driver to test it out. * * @param args command-line arguments (not currently used) */ public static void main(String[] args) { final int numTimes = 3; String[] hellos = {"Ola", "Aloha", "Bon Jour",}; Greeting greeting = new Greeting("Unknown program user"); greeting.say(); greeting = new Greeting(); for (int i = 0; i < numTimes; i++) { greeting.say(hellos[i]); } } }
This is the good sample Java class from above, but with a couple of style errors. The next section below shows the results of checking the style of this file.
[BACK TO TOP]/** * Greeting.java * */ import java.util.Scanner; /** * An obfuscated HelloWorld program to demonstrate coding style. * * A dual-purpose class to (1) play with the classic first program * "Hello World", and (2) demonstrate proper coding styles. Note that * to invoke a large number of style issues, the code is somewhat * (okay, largely :) obfuscation. * * @version Dec 2011 */ public class Greeting { private static final String DEFAULT_INTRO = "Hello"; private String user; private Scanner keyboard; /** * Parameterless constructor, initializes keyboard input. */ public Greeting() { keyboard = new Scanner(System.in); } /** * Alternate constructor. * */ public Greeting(String u) { /* Notice this nifty way to initilize the keyboard Scanner WITHOUT duplicating code by invoking the other constructor. */ this(); user = u; } /** * Builds a greeting. * * Uses Scanner object to get input from keyboard for customization. * * @param introduction user's customized greeting intro (e.g., G'day) * @return a customized greeting */ private String make(String introduction) { String greeting = "Hello"; if (introduction != null) { greeting = introduction; } // Customize with user's name! if (user == null) { System.out.print("Please enter your name: "); user = keyboard.nextLine(); } greeting = greeting + ", " + user + "."; return greeting; } /** * Says default greeting. */ public void say() { /* Notice the nifty way to use overloaded method to avoid code duplication! */ say(DEFAULT_INTRO); } /** * Says the greeting. * * Uses private internal method to customize. * * @param intro passing through user's greeting customization */ public void say(String intro) { String greeting = make(intro); System.out.println(greeting); } /** * Driver to test it out. * * @param args command-line arguments are not used currently */ public static void main(String[] args) { final int numTimes = 3; String[] hellos = {"Ola", "Aloha", "Bon Jour"}; Greeting greeting = new Greeting("Unknown program user"); greeting.say(); greeting = new Greeting(); for (int i=0; i < numTimes; i++) { greeting.say(hellos[i]); } } }
Here is the output of the command-line checkstyle automated checker.
Greeting.java did not pass checkstyle Starting audit... Greeting.java:5: Line does not match expected header line of '^ \* @author .*$'. Greeting.java:37:28: Expected @param tag for 'u'. Greeting.java:104:19: Name 'numTimes' must match pattern '^[A-Z][A-Z0-9_]*$'. Greeting.java:111:19: '=' is not preceded with whitespace. Greeting.java:111:20: '=' is not followed by whitespace. Audit done.
Each audit line indicates the file, line number, and an warning/error message. Optionally, a column value is given. The output above indicates 4 style violations: