This is a set of style guidelines for for JDK Release Projects in the OpenJDK Community. Other OpenJDK Projects, and projects outside of OpenJDK, are welcome to adopt these guidelines as they see fit.
Code that looks familiar is easier to understand and therefore also easier to review, debug and maintain. To ensure that code looks familiar to all developers on the project it’s important to agree on a common set of style guidelines.
This document provides guidelines for low level coding practices such as how to indent code and how to name types and variables. Many of the stylistic choices are subjective and different developers may have different opinions about them. Keep in mind however, that having a consistent style is more important than to satisfy each individual developers preference.
The guidelines in this document strive to maximize,
While this document covers a lot of ground, it should be noted that no style guide can answer all questions for us, and developers will always need to use good judgment towards the end of producing code that is correct, readable, maintainable, debuggable, consistently formatted, and aesthetically pleasing.
Examples in this document are non-normative; While they intend to illustrate correct way of formatting the code, there may be other ways to correctly format the code. This is a general principle: There may be several ways to format the code, all adhering to the guidelines in this document.
Tool support is nice, but ultimately each IDE and style checking tool can handle different sets of rules, and support for rules that can’t be handled today might be added in future versions. So, whether a rule plays well with tools or not can be a factor, but it’s secondary to the above principles.
This section concerns ordinary .java
files only. Rules do not necessarily apply to other source files in the project such as .jasm
, .sh
or .gmk
.
LF
, ASCII value 10) and not for instance CR
or CR
+LF
..java
extension, even for files that only contain a package private class. This does not apply to files that do not contain any class declarations, such as package-info.java
.7-bit ASCII reduces errors due to confusion of characters since there are no invisible spaces, characters that look like minus signs but are really dashes, etc. It also ensures packages and classes are named in such way that the corresponding directories and source files are portable across different filesystems.
Agreeing on a common line delimiter character is important since different operating systems have different defaults. Editing a file on Windows that was originally written on Linux, may cause all LF
to be saved back as CR
+LF
. This creates an unnecessarily big patches and may not display correctly in the text editor it was originally written in. A single line feed character is default for Unix-like systems and supported by all common text editors and IDEs.
Trailing white space is nothing but unnecessary cruft. It’s easy to remove and agreeing on doing so consistently minimizes diffs.
Not using the name of the class as filename can be confusing. Also, unless the file is given explicitly to the compiler, the class it contains may not be resolved correctly.
LF
the only allowed white space character is Space (ASCII value 32). Note that this implies that other white space characters (in, for instance, string and character literals) must be written in escaped form.\'
, \"
, \\
, \t
, \b
, \r
, \f
, and \n
should be preferred over corresponding octal (e.g. \047
) or Unicode (e.g. \u0027
) escaped characters.
Having any white space character but space and LF
in the source code can be a source of confusion.
The short forms (e.g. \t
) are commonly used and easier to recognize than the corresponding longer forms (\011
, \u0009
).
.java
source file should be structured as follows:
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
or
/*
* Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
where the first year is the year the file was created and the second year is the year the file was last edited.
For questions regarding copyright or license notices, please contact iris.clark@oracle.com.
java
packagesjavax
packagesorg.xml
)com.sun
)Wildcard imports makes it unclear what actually needs to be imported.
Having more than one wildcard import makes the code fragile since adding a new class in one of the imported packages can introduce a name clash.
An unused import gives a false impression of a dependency. Also, many IDEs list such import statements as warnings which clutters the list of problems.
The recommended order of class members is the following:
public HashSet() {
this(DEFAULT_INITIAL_CAPACITY);
}
public HashSet(int capacity) {
this(capacity, DEFAULT_LOAD_FACTOR);
}
public HashSet(int capacity, double loadFactor) {
…
}
// Overloaded methods should not be split apart
void logValue(int i) {
log("Int: %d", i);
}
void setValue(int i) {
val = i;
}
void logValue(double d) {
log("Double: %.2d", d);
}
void setValue(double d) {
val = d;
}
This order puts the most generally applicable versions first. Also, making sure delegation is always done downwards in the file makes the code easier to follow.
public
/ private
/ protected
)abstract
static
final
transient
volatile
default
synchronized
native
strictfp
Writing out modifiers where they are implicit clutters the code and learning which modifiers are implicit where is easy.
Although method parameters should typically not be mutated, consistently marking all parameters in every methods as final
is an exaggeration.
Making fields immutable where possible is good programming practice. Refer to Effective Java, Item 15: Minimize Mutability for details.
Braces are recommended even where the language makes them optional, such as single-line if and loop bodies.
else
, catch
and the while
keyword in do
…while
loops go on the same line as the closing brace of the preceding block.void method() {
…
}
try {
something();
} catch (AnException e) {
…
}
for (int[] row : matrix) {
for (int val : row) {
sum += val;
}
}
// Wrong placement of opening brace
void method()
{
…
}
// Newline in front of catch should be avoided
try {
something();
}
catch (AnException e) {
…
}
// Braces should be used
if (flag)
// Restore x
x = 1;
// Use braces if block comes last in enclosing block
// to avoid accidentally indenting the closing brace.
for (int[] row : matrix) {
for (int val : row)
sum += val;
}
Putting opening braces on the end of the line (as opposed to on a line of its own) is a long standing Java convention. This style is also suitable for Java, considering that it’s common to have small blocks (in for instance anonymous classes and lambda expressions) and having opening braces on a separate line creates an unnecessary amount of white space in such situations.
Omitting braces is error prone and can lead to mistakes in the indentation and hard to detect bugs.
enum Response { YES, NO, MAYBE }
public boolean isReference() { return true; }
public boolean getResult() { int value = getValue(); return value < 0 ? 0 : value; }
for (int i = 0; i < size; i++) { sum += data[i]; }
case
lines should be indented with four spaces, and statements within the case should be indented with another four spaces.
Existing code that follows the old style of not indenting case
lines (see Don’ts example below) is acceptable to leave as is.
switch (var) {
case TWO:
setChoice("two");
break;
case THREE:
setChoice("three");
break;
default:
throw new IllegalArgumentException();
}
switch (var) {
case TWO:
setChoice("two");
break;
case THREE:
setChoice("three");
break;
default:
throw new IllegalArgumentException();
}
By using spaces for indentation, problems regarding different default settings for tab stops in various editors are avoided.
Source code and comments should generally not exceed 80 characters per line and rarely if ever exceed 100 characters per line, including indentation.
The character limit must be judged on a case by case basis. What really matters is the semantical “density” and readability of the line. Making lines gratuitously long makes them hard to read; similarly, making “heroic attempts” to fit them into 80 columns can also make them hard to read. The flexibility outlined here aims to enable developers to avoid these extremes, not to maximize use of monitor real-estate.
// Ok even though it might exceed max line width when indented.
Error e = isTypeParam
? Errors.InvalidRepeatableAnnotationNotApplicable(targetContainerType, on)
: Errors.InvalidRepeatableAnnotationNotApplicableInContext(targetContainerType));
String pretty = Stream.of(args)
.map(Argument::prettyPrint)
.collectors(joining(", "));
// Too strict interpretation of max line width. Readability suffers.
Error e = isTypeParam
? Errors.InvalidRepeatableAnnotationNotApplicable(
targetContainerType, on)
: Errors.InvalidRepeatableAnnotationNotApplicableInContext(
targetContainerType);
// Should be wrapped even though it fits within the character limit
String pretty = Stream.of(args).map(Argument::prettyPrint).collectors(joining(", "));
aMethodCall(withMany(arguments, that, needs),
to(be, (wrapped - to) * avoid / veryLong - lines));
aMethodCall(withMany(arguments, that, needs), to(be, (wrapped
- to) * avoid / veryLong - lines));
i += j;
j += k;
if (condition) {
return expression;
}
i += j; j += k;
if (condition) { return expression; }
// Variant 1
int anInteger = aMethod(that, takes,
a, lengthy, list, of, arguments);
// Variant 2
int anInteger = that * (is + computed) / using
+ a * complex - expression;
// Variant 3
int anInteger = aMethod(thatTakes,
aLongList,
ofArguments);
// Variant 4
int anInteger = IntStream.of(numbers)
.map(Math::sqrt)
.sum();
// Mixing of wrapping variants (unless there
// is a logical grouping of arguments)
int anInteger = aMethod(that,
takes,
a, lengthy, list,
of, arguments);
// Don't align with sibling expression if the continuation
// line can be confused with a block indentation
if (somePredicate() ||
someOtherPredicate()) {
System.out.println("Avoid");
}
extends
and/or implements
keywords.public class MyGenericClass<T, S>
extends HashMap<T, S>
implements Comparable<T> {
…
}
public class AnotherClass<K, R> implements Collector<T extends K,
Set<? extends R>,
List<R>> {
…
}
public class MyGenericClass<T> implements Comparable<T>,
Predicate<T> {
…
}
int someMethod(String aString,
List<Integer> aList,
Map<String, String> aMap,
int anInt,
long aLong,
Set<Number> aSet,
double aDouble) {
…
}
int someMethod(String aString, List<Integer> aList,
Map<String, String> aMap, int anInt, long aLong,
double aDouble, long aLong) {
…
}
int someMethod(String aString,
List<Map<Integer, StringBuffer>> aListOfMaps,
Map<String, String> aMap)
throws IllegalArgumentException {
…
}
int someMethod(String aString, List<Integer> aList,
Map<String, String> aMap, int anInt)
throws IllegalArgumentException {
…
}
// If aligning the parameters vertically, don't put two
// parameters on one line
int someMethod(String aString,
List<Integer> aList,
Map<String, String> aMap,
int anInt, long aLong,
Set<Number> aSet,
double aDouble) {
…
}
int someMethod(String aString,
List<Map<Integer, StringBuffer>> aListOfMaps,
Map<String, String> aMap) throws InterruptedException {
…
}
int someMethod(String aString,
List<Integer> aList,
Map<String, String> aMap)
throws IllegalArgumentException {
…
}
.
in chained method calls.methodCall(a * simple - formula,
some + complex - formula * spanning
+ multiple - lines * may
+ look - as * follows);
popupMsg("Inbox notification: You have "
+ newMsgs + " new messages");
persons.stream()
.map(Person::getName)
.forEach(System.out::println);
// Arity unclear
methodCall(a * simple - formula,
some + complex - formula * spanning +
multiple - lines * should + not *
look - as * follows);
// Looks like two arguments
popupMsg("Inbox notification: You have " +
newMsgs + " new messages");
persons.stream().
map(Person::getName).
forEach(System.out::println);
…and may be used to separate logical groups of
//
that starts a comment.int someInt;
String myString;
char aChar;
long sixtyfourFlags;
if (isFlagSet(GO)) {
…
}
IntUnaryOperator inc = x -> x + 1;
init: {
…
}
int someInt;
String myString;
char aChar;
long sixtyfourFlags;
if( isFlagSet( GO ) ) {
…
}
IntUnaryOperator inc = x->x + 1;
init : {
…
}
The improvement in readability when aligning variable names is negligible compared to the efforts needed to keep them aligned as the code evolves. Realigning all variables when one of the types change also causes unnecessarily complicated patches to review.
String[] args
) and not on the variable (String args[]
).@Deprecated
@Override
public void foo() {
…
}
@Deprecated @Override
public void foo() {
…
}
addListener(new Listener() {
// Ignored events
@Override public void event1() { }
@Override public void event2() { }
@Override public void event3() { }
// Important event
@Override
public void event4() {
…
}
});
@Override @Deprecated public void foo() {
…
}
@Override @Deprecated
@SafeVarargs
public void foo() {
…
}
Method references should generally be preferred over lambda expressions.
For bound instance method references, or methods with arity greater than one, a lambda expression may be easier to understand and therefore preferred. Especially if the behavior of the method is not clear from the context.
Runnable r = () -> System.out.println("Hello World");
Supplier<String> c = () -> "Hello World";
// Collection::contains is a simple unary method and its behavior is
// clear from the context. A method reference is preferred here.
appendFilter(goodStrings::contains);
// A lambda expression is more readable in this case
// (cf. corresponding example in Don'ts section)
trackTemperature((time, temp) -> tempMap.put(time, temp));
Function<Person, String> nameFunc = p -> p.getFirstName() + " " + p.getLastName();
class Util {
private static String getCapitalizedFirstName(Person p) {
String first = p.getFirstName();
char initial = Character.toUpperCase(first.charAt(0));
return initial + first.substring(1);
}
static void printAllPersons(List<Person> persons) {
persons.stream()
.map(Util::getCapitalizedFirstName)
.forEach(System.out::println);
}
}
Runnable r = () -> { System.out.println("Hello World"); };
Supplier<String> s = () -> { return "Hello World"; };
// A lambda expression is not needed here
appendFilter(s -> goodStrings.contains(s));
// Map::put is a binary function, and it's not clear from context what type
// of argument trackTemperature accepts. A lambda expression is better here.
trackTemperature(tempMap::put);
// Unnecessary parameter type
Function<Person, String> nameFunc = (Person p) -> p.getFirstName() + " " + p.getLastName();
class Util {
static void printAllPersons(List<Person> persons) {
persons.stream()
.map(p -> {
String first = p.getFirstName();
char initial = Character.toTitleCase(first.charAt(0));
return initial + first.substring(1);
})
.forEach(System.out::println);
}
}
return flag ? "yes" : "no";
String cmp = (flag1 != flag2) ? "not equal" : "equal";
return (flag ? "yes" : "no");
long
literals should use the upper case letter L
suffix.A
-F
.long l = 5432L;
int i = 0x123 + 0xABC;
byte b = 0b1010;
float f1 = 1 / 5432f;
float f2 = 0.123e4f;
double d1 = 1 / 5432d; // or 1 / 5432.0
double d2 = 0x1.3p2;
long l = 5432l;
int i = 0X123 + 0xabc;
byte b = 0B1010;
float f1 = 1 / 5432F;
float f2 = 0.123E4f;
double d1 = 1 / 5432D;
double d2 = 0x1.3P2;
Lower case L resembles a 1 in many monospace fonts which means that the literal 5432l
can be confused with 54321
. Using upper case L
suffix avoids this. The lowercase 0x
, 0b
, e
, p
, f
, and d
characters are easier to spot in a long sequence of digits, and they avoid confusion with the hexadecimal digits A
-F
.
This section only covers basic Javadoc formatting. For a complete reference refer to How to Write Doc Comments for the Javadoc Tool.
{@code …}
and {@link …}
etc) over corresponding HTML tags (<code>…</code>
, <a href="…">…</a>
etc).<p>
to separate paragraphs (closing </p>
tags are not needed and should not be used)/** A short javadoc comment */
/**
* …
*
* <blockquote>{@code
* List<String> names;
* }</blockquote>
*/
/** put on single line instead
*/
/**
* The <String> below may interfere with the HTML!
*
* <blockquote><pre>
* List<String> names;
* </pre></blockquote>
*/
java.lang.annotation
and not java.lang.annotations
.class EmptyCell {
…
}
class RunningMode {
…
}
interface Expandable {
…
}
class XmlParser {
…
}
class Empty {
…
}
class Running {
…
}
class Expandable {
…
}
// Abbreviation should be formatted as 'Xml'
class XMLParser {
…
}
public void expand() {
…
}
public boolean isExpanding() {
…
}
public State getState() {
…
}
public boolean expanding() {
…
}
public State GetState() {
…
}
public int get_index() {
…
}
int currentIndex;
boolean dataAvailable;
int current_index;
boolean DataAvailable;
K
and V
for keys and values in maps or R
for a function return type) use that, otherwise use T
._
) to separate words.interface SpecialMap<K, V> extends Map<K, V> {
…
}
class GraphMapper<SRC_VERTEX, SRC_EDGE, DST_VERTEX, DST_EDGE> {
…
}
interface SpecialMap<Key, Value> extends Map<Key, Value> {
…
}
class GraphMapper<S, T, U, V> {
…
}
_
) to separate words.public static final int BUFFER_SIZE = 1024;
enum ApplicationMode { RUNNING, PAUSED, TERMINATED }
public final List<String> CURRENT_WORDS = new ArrayList<>();
enum ApplicationMode { Running, Paused, Terminated }
The focus of the guidelines in this document is on style. General guidelines on best programming practices, use of design patterns, how to structure programs etc is thus out of scope. A few “low level” practices that are easy to pin down is however good to agree upon.
@Override
where it is possible to do so.TODO
” comments. If the missing code doesn’t affect correctness or performance, skip the comment, otherwise file an issue for it.// fall through
” comment.//
) otherwise use multiline comments (/* … */
).Cleaning up code that’s unrelated to the patch may…