Skip to content
Yevhenii Voevodin edited this page Nov 30, 2015 · 2 revisions

Indentation

Right margin(column limit) is 140 characters

If code exceeds margin it must be divided on multiple lines.

Exceptions from this rule:

  • Package statement must be declared in a single line
  • Each import statement must be declared in a single line
  • Any information in comment which is important in original view such as bash command (which may be copied) also may be declared in one line

Block indentation is +4 spaces

Each new code block must be indented with +4 spaces, after block ends indent must be returned to previous position.

Note that tab character must not be used for indentation according to this rule

One statement per one line

Each statement must be followed by line break.

// Good
i++;
j++;
// Not allowed, 2 statements in a single line
i++; j++;

Braces

Non-empty blocks

For statements if, else, for, do, while braces must be used even when block contains an empty body or a single statement.

For all non-empty blocks Egyptian style must be used:

  • No line break before the opening brace
  • Line break after the opening brace
  • Line break before the closing brace
  • Line break after the closing brace when this brace terminates statement
public class Example {

    public static void main(String[] args) {
        if (isOkay()) {
            doSomething();
        } else {
            doSomethingElse();
        }
    }
}

Empty blocks

Empty block may be immediately closed after it is opened, when this block is related to constructor, method or anonymous class declaration.

private Constants() {}
public void doNothing() {}
Type type = new TypeToken<List<String>>() {}.getType();

Blank lines

Single blank line:

  • Between class members: fields, methods, constructors, nested classes, initializers except of logical groupings of fields
  • Optional: between logical groupings of statements
  • Optional: before the first member or after the last member of the class
  • As required by this document(i.e. import statements, package declaration)

Multiple blank lines:

Multiple blank lines are not required.

Line wrapping

Almost always you have several ways to wrap the code, there is no any algorithm which will tell you what exactly to do, but still you must follow some basic rules:

Constructor or method name is always attached to the left open parenthesis(
// Good
public static void doSomething(double arg1,
                               double arg2,
                               double arg3,
                               double arg4,
                               double arg5,
                               double arg6) {
    //...
}
// Not Allowed, left open parenthesis is not attached to the constructors name
public static void doSomething
                   (double arg1,
                    double arg2,
                    double arg3,
                    double arg4,
                    double arg5,
                    double arg6) {
    //...
}
Comma , is always attached to the related statement
// Good
void doSomeStuff() throws Exception1, Exception2, Exception3 {
    //...
}
// Not allowed, comma should be attached to the related statement
// but there are spaces before related statements and the comas
void doSomeStuff() throws Exception1 , Exception2 , Exception3 {
    //...
}
// Not allowed, comma should be attached to the related statement
// but there are line breaks before the related statements and the comas
void doSomeStuff() throws Exception1
                          ,Exception2
                          ,Exception3 {
    //...
}
For dot . separator break always comes before the symbol:
// Good
workspaces.stream()
          .map(this::asDto)
          .collect(toList());
// Not allowed, break should go before the '.'
workspaces.stream().
           map.
           collect(toList());
For assignment operator the break comes after the symbol
Element project =
    createElement("project",
                  createElement("parent",
                                createElement("groupId", "com.codenvy")));
For any other operator the break comes before the symbol
return Objects.equals(owner, other.owner)
       && Objects.equals(id, other.id)
       && Objects.equals(name, other.name)
       && Objects.equals(defaultEnvName, other.defaultEnvName)
       && Objects.equals(status, other.status)
       && isTemporary == other.isTemporary
       && commands.equals(other.commands)
       && environments.equals(other.environments)
       && projects.equals(other.projects)
       && attributes.equals(other.attributes);
try {
    doSomeStuff();
} catch (IOException
         | ConflictException
         | NotFoundException
         | ForbiddenException
         | ServerException ex) {
    handle(ex);
}

Spaces

  • Before open parentheses ( for any of keywords if, else, for, while, switch, try, catch, synchronized

  • Around operators

    • Assignment operators =, &=, ...
    • Logical operators &&, ||
    • Equality and relational operators ==, >, <=, ...
    • Binary operators &, |, ^
    • Additive operators +, -
    • Multiplicative operators * , /, %
    • Shift operators <<, >>, >>>
    • Lambda arrow ->
  • Before left brace {

    • After class declaration
    public class Example {
    • After method declaration
    public void doSomeStuff() {
    • Before left brace which goes after any of keywords if, else, for, while, do, switch, try, catch, finally, synchronized
  • Before any of keywords else, while (when it used with do), catch, finally

  • In ternary operator ?:

    • Before ?
    • After ?
    • Before :
    • After :
int value = (x < y) ? -1 : 1;
  • After comma , or semicolon ;(for loop)
Map<String, String> map = new HashMap<>();
for (int i = 0; i < count; i++) {
    //..
}

Alignment

Align when multi-line

  • Throws list
public void longMethodName(String arg1) throws Exception1,
                                               Exception2,
                                               Exception3,
                                               Expcetion4 {
  • Method declaration parameters
public void foo(String arg1,
                String arg2,
                String arg3,
                String arg4,
                String arg5,
                String arg6,
                String arg7) {
  • Method call arguments
String value = foo("arg1",
                   "arg2",
                   "arg3",
                   "arg4",
                   "arg5",
                   "arg6",
                   "arg7");
  • Chained method calls
Optional<MachineDto> machineDto = machines.stream()
                                          .filter(Machine::isDev)
                                          .map(this::asDto)
                                          .findFirst();
  • Try with resources
try (BufferedReader inReader = newBufferedReader(proc.getInputStream());
     BufferedReader errReader = newBufferedReader(proc.getErrorStream())) {
    //..
} catch (Exception ex) {
    handle(ex);
}
  • Ternary operator
int value = (x + y + z < 0xFFFFFF) ?
            veryLongMethodName(x, y) :
            veryLongMethodName(x + z);
  • Array initializer
int[] powerOf2 = new int[] {1 << 1,
                            1 << 2,
                            1 << 3,
                            1 << 4}
  • Annotation parameters
@Annotation(param1 = "value1",
            param2 = "value2",
            param3 = "value3",
            param4 = "value4")
public void doSomeStuff() {

Fields alignment

Horizontal alignment is not required but preferable.

// Good, but requires formatting after modification
private static final Pattern WS_NAME       = Pattern.compile("\\w+");
private static final int     DEFAULT_COUNT = 10;

private final WorkspaceDao  workspaceDao;
private final MemberDao     memberDao;
private final PreferenceDao preferenceDao;
// Also good, doesn't require formatting after modification
private static final Pattern WS_NAME = Pattern.compile("\\w+");
private static final int DEFAULT_COUNT = 10;

private final WorkspaceDao workspaceDao;
private final MemberDao memberDao;
private final PreferenceDao preferenceDao;

Arrays

  • Arrays may be initialized in any way
int[] ints = new int[] {0xAF, 0xBF, 0xCF, 0xDF};

int[] ints2 = new int[] {0xAF,
                         0xBF,
                         0xCF,
                         0xDF};

int[] ints3 = new int[] {0xAF, 0xBF,
                         0xCF, 0xDF};
  • Square brackets are part of the type int[] ints not of the variable int ints[]

Switch statement

  • Each case statement ends either with break, return, continue, throw statement or fall throught comment(when case is non-empty)
  • default statement is always present even when it is empty
switch (line) {
    case "-f":
    case "--force":
        doForceAction();
        break;
    case "--verbose-out":
        setVerboseOutput(true);
        // fall throught
    case "--out":
        doOutput();
        break;
    default:
        //nothing to do
}

Annotations

  • Annotation which is applied not on the method argument always comes in a new line
@Path("/workspace")
public class WorkspaceService {
@GET
@Path("/workspaces")
@Produces("application/json")
public String getWorkspaces() {
@Override
public int hashCode() {
@Inject
@Named("property")
private String property;
@SuppressWarnings("unchecked")
List<String> list = getNames();
  • Annotation(s) applied on method argument preferable used in the same line as argument
public List<Workspace> getWorkspaces(@PathParam("owner") String owner) {
public void doSomeStuff(@NotNull String argument) {
public List<Workspace> getWorkspaces(@Req @QueryParam("limit") int limit) {
//one line annotations definition exceeds right margin
//in this case it should be defined in multi-lines
//and aligned with argument type
public List<Workspace> getWorkspaces(@ApiParam("workspaces limitation")
                                     @DefaultValue("30")
                                     @QueryParam("limit")
                                     int limit) {

Modifiers order

The following modifiers order is required:

  • Access modifier public, protected,private
  • static
  • default
  • final
  • synchronized
  • volatile
  • transient
  • native
  • abstract
  • strictfp

You should not write modifier when it is implicitly defined, for example interface methods are public & abstract by default.

Javadoc

Generally

  • Short javadoc may be defined in one line
/** Returns identifier of user which is currently logged */
public String getUserId() {
  • @param, @return, @throws or @deprecated must not be appeared without of description

  • @param and @throws description must be defined in a new line and aligned with other descriptions

/**
 * Gets list of workspaces owned by given user.
 *
 * @param owner
 *         workspace owner identifier
 * @return the list of workspaces, never null
 * @throws ServerException
 *         when any server error occurs
 */
 List<Workspace> getWorkspaces(String owner) throws ServerException;

Paragraphs

  • Empty line appears before paragraph
  • Paragraph starts with paragraph identifier <p> without any additional spaces
/**
 * Starts {@link Workspace workspace} with given environment.
 *
 * <p>Starts all machines in certain starting from dev-machine
 *
 * @param workspace
 *         workspace which is going to be started
 * @param envName
 *         environment name or null, when default one should be used
 */
 public void start(Workspace workspace, String envName) {

At-clauses order

The following order is required for standard at-clauses:

  • @param
  • @return
  • @throws
  • @deprecated

Numeric literals

For long, float, double literals uppercase suffix must be used

long longValue = 123L;
float floatValue = 0.25F;
double doubleValue = 0.25D;