Topjava — онлайн-школа по обучению программированию на самом популярном в мире языке Java
Первое занятие бесплатно
Руководство Google по стилистике написания кода на Java. Часть 2
4 Форматирование
Терминология

Тело класса, метода или конструктора относится к Блочной конструкции

Обратите внимание, что согласно Разделу 4.8.3.1, любой инициализатор массива также может рассматриваться как блочная конструкция.
4.1 Фигурные скобки
4.1.1 Фигурные скобки используются везде, где они могут быть использованы
Фигурные скобки используются в if, else, for, while и do-while, даже если тело выражения пустое или содержит лишь одну строку кода.
4.1.2 Непустые блоки: стиль K & R
Фигурные скобки ставятся согласно стилю Кернигана и Ритчи («Египетские скобки») для непустых блоков и блочных конструкций:

  • Перед открывающейся скобкой переход на новую строку не делается:
// правильно
if (true) { 

// неправильно
if (true)
{
  • Переход на новую строку делается после открывающей скобки:
// правильно
while (true) {
  // code

// неправильно
while (true) { // code
  • Переход на новую строку делается перед закрывающей скобкой:
// правильно
for () {
  // code
}

// неправильно
while (true) { /* code */ }

// неправильно
if (true) {
  /* code */ }
  • Переход на новую строку делается после закрывающей скобки, только если эта скобка завершает выражение или тело метода, конструктора или именованного класса. Например, переход на новую строку не делается после скобки, если за ней следует else, catch или точка с запятой:
// правильно
try {
    something();
    } catch (ProblemException e) {
    recover();
    }

// неправильно
try {
    something();
    } 
catch (ProblemException e) {
    recover();
    }
Примеры правильно выполненных правил:
return () -> {
  while (condition()) {
    method();
  }
};

return new MyClass() {
  @Override public void method() {
    if (condition()) {
      try {
        something();
      } catch (ProblemException e) {
        recover();
      }
    } else if (otherCondition()) {
      somethingElse();
    } else {
      lastThing();
    }
  }
};
Некоторые исключения для классов enum приведены в Разделе 4.8.1, Классы enum.
4.1.3 Пустые блоки могут быть сжатыми
Пустой блок или пустая блочная конструкция может следовать стилю K & R (как описано в Разделе 4.1.2). Также возможно, чтобы такой блок (или блочная конструкция) был закрыт сразу же после открытия, без символов или разрыва строки внутри ({}), кроме случая, когда он является частью многоблочного выражения (такого, которое содержит различные блоки: if/else или try/catch/finally

Примеры:

// Приемлемо
  void doNothing() {}

// Также приемлемо
  void doNothingElse() {
  }
// Неприемлемо: нельзя использовать пустые блоки в многоблочном выражении
  try {
    doSomething();
  } catch (Exception e) {}
4.2 Отступ блока: +2 пробела
Каждый раз, когда открывается новый блок или блочная конструкция, смещение увеличивается на два пробела. Когда блок заканчивается, начало строки смещается на предыдущий уровень смещения. Уровень смещения применяется как к блоку, так и к комментариям в этом блоке. (См. Пример в Разделе 4.1.2. Не пустые блоки: Стиль K & R)
4.3 Одно выражение на каждую строку
Каждое выражение завершается переходом на новую строку.
4.4 Ширина строки: 100 символов
Java-код имеет ограничение в 100 символов по ширине строки. Под «символом» понимается любой из элементов Unicode. За исключением случаев, описанных ниже, каждая строка с превышением ограничения по ширине, должна быть перенесена так, как это объяснено в Разделе 4.5, Перенос строки.
Каждый элемент Unicode считается как один символ, даже если его отображение больше или меньше по ширине. Например, при использовании полноформатных символов, можно сделать перенос строки раньше, чем этого требуют данные правила.
Исключения:

  1. Строки, в которых соблюдение ограничения по ширине не возможно (например, длинная ссылка URL в Javadoc или длинная JSNI-ссылка на метод).
  2. Объявления package и import (см. Разделы 3.2 Объявление пакета и 3.3 Объявления импортов).
  3. Коммандные строки в комментариях, которые могут быть скопированы и вставлены для выполнения в среде.
4.5 Перенос строки
Терминология

Когда код, который в другом случае мог бы быть расположен на одной строке, разделяется на несколько строк, это явление называется переносом строки.
Не существует общепринятой однозначной формулы, определяющей, как именно надо делать перенос строки в каждой ситуации. Очень часто есть несколько верных путей для переноса строки с одним и тем же фрагментом кода.
При том, что обычно перенос строки делается во избежание переполнения строки по ширине, даже код, который на самом деле остался бы в пределах разрешенной ширины, может быть перенесен на новую строку по решению автора.
Выделение вспомогательного метода или локальной переменной может решить проблему без переноса строки.
4.5.1 Где делать перенос
Первое указание по переносу строки гласит: предпочтительнее делать перенос на высшем синтаксическом уровне. Также:
1. Когда строка переносится не на операторе присваивания, перенос делается перед символом. (Заметьте, что иная практика стилей Google используется в других языках программирования, таких как C++ и JavaScript.)

Это правило также применимо к следующим «оператороподобным» символам:
  • разделяющая точка ( . )
  • двойное двоеточие ссылочного метода ( :: )
  • амперсанд в скобках дженерика ( <T extends Foo & Bar> )
  • разделитель в блоке catch ( catch ( FooException | BarException e) ).
2. Когда строка переносится на операторе присваивания, перенос обычно делается после символа, но приемлемо и другое решение.

Это также применимо к двоеточию в расширенном выражении для цикла for («for-each»).
3. Имя метода или конструктора при переносе строки остается с открытой скобкой ( ( ).
4. Запятая ( , ) при переносе строки остается с элементом, который ей предшествует.
5. Строка никогда не переносится непосредственно у стрелки лямбда-выражения, кроме случаев, когда его тело состоит из одного выражения без фигурных скобок.
MyLambda<String, Long, Object> lambda =
    (String label, Long value, Object obj) -> {
        ...
    };

Predicate<String> predicate = str ->
    longExpressionInvolving(str);
Главная цель переноса строки - добиться ясности кода, но не обязательно наименьшего количества строк.
4.5.2 Смещение продолжения строки на 4 и более пробела
При переносе строки каждая следующая ее подстрока (каждое продолжение строки) смещается как минимум на 4 пробела относительно предыдущей.

Когда продолжений строки несколько, смещение может варьироваться в пределах 4 пробелов по желанию автора. По общему правилу, два продолжения строки могут иметь одинаковое смещение тогда и только тогда, когда они начинаются с синтаксически параллельных элементов.

Раздел 4.6.3 по Горизонтальному выравниванию дает указания по использованию различного количества пробелов для выравнивания элементов кода относительно предыдущих строк.
4.6 Пробелы и отступы
4.6.1 Отступы
Одна пустая строка всегда ставится:

1. Между следующими друг за другом членами или инициализаторами класса: полями, конструкторами, методами, вложенными классами, статическими и динамическими блоками инициализации.

  • Исключение: Пустая строка между двумя последовательными полями (без кода между ними) используется опционально. При необходимости пустые строки используются для логического группирования полей.
  • Исключение: Пустые строки между константами класса enum (см. Раздел 4.8.1).
2. В соответствии с другими разделами данного документа (например, с Разделом 3, Структура исходного файла, и Разделом 3.3, Объявления импортов).

Пустая строка также может быть использована повсеместно для повышения читаемости кода, например, между выражениями для организации кода в логические подразделы. Пустая строка перед первым членом класса или блоком инициализации или после последнего члена или блока инициализации класса не приветствуется, но и не возбраняется.

Несколько последовательных пустых строк делать разрешается, но это не необходимо и не приветствуется.

4.6.2 Пробелы
Помимо требований самого языка или прочих правил данного документа, а также не считая литералов и комментариев (в т. ч. Javadoc), одиночные пробелы из таблицы ASCII могут присутствовать только в следующих местах:

1. При разделении любого зарезервированного слова, такого как if, for или catch, и открывающей круглой скобки ((), которая следует за ним.

2. При разделении любого зарезервированного слова, такого как else или catch, и закрывающей фигурной скобки (}), которая следует за ним.

3. Перед любой открывающей фигурной скобкой ({), за исключением двух ситуаций:
  • не использован пробел
  • пробел между {{ не нужен согласно п. 8 ниже
4. По обе стороны от любого бинарного или тернарного оператора. Это правило также применимо к следующим «оператороподобным» символам:
  • амперсанд внутри угловых скобок: <T extends Foo & Bar>
  • разделитель в блоке catch, содержащем несколько исключений: catch (FooException | BarException e)
  • двоеточие ( : ) в расширенном выражении for («for-each»)
  • стрелка в лямбда-выражении: (String str) -> str.length(
Но это правило не применимо к следующим:
  • двойное двоеточие ( :: ) ссылочного метода, которое пишется как Object::toString
  • разделяющая точка ( . ), которая пишется как object.toString()
5. После , : ; или закрывающей круглой скобки при приведении типа

6. По обе стороны от двойной косой черты ( // ) при создании комментария в той же строке кода. Здесь разрешены, но не необходимы несколько пробелов.

7. Между объявлением типа и именем переменной: List<String> list

8. Опционально: внутри скобок инициализатора массива
  • new int[] {5, 6} и new int[] { 5, 6 } - оба варианта верные

Это правило не требует наличия или отсутствия пробелов в начале или конце строки; правило относится лишь к внутренним пробелам.

4.6.3 Горизонтальное выравнивание не требуется никогда
Терминология

Горизонтальное выравнивание - это практика добавления различного числа дополнительных пробелов в вашем коде с целью сделать так, чтобы определенные элементы были расположены под другими элементами с предыдущей строки.
Эта практика разрешена, но она никогда не требуется согласно Стилям Google. Также не требуется поддерживать соблюдение выравнивания в тех участках кода, где оно уже было применено.

Вот пример без выравнивания, а затем - с использованием выравнивания:
private int x; // хорошо
private Color color; // и это тоже

private int   x;      //  разрешено, но при редактировании в будущем
private Color color;  // можно оставить без выравнивания
Выравнивание способствует читаемости кода, но создает проблемы для обработки в будущем. Рассмотрим изменение в будущем, при котором требуется затронуть только одну строку. Это изменение может исказить ранее приятный для чтения код, и это допускается. Гораздо чаще это толкает программиста (возможно, вас) на корректировку количества пробелов на рядом стоящих строках и, возможно, запускает целую череду форматирований. Это изменение одной строки теперь действует «взрывная волна.» В худшем случае это приведет к бессмысленному труду, но и в лучшем случае это приводит к искажению информации об истории версий, тормозит чтение кода и обостряет конфликты слияния.
4.7 Группирующие скобки рекомендованы
Допускается не ставить группирующие скобки только тогда, когда автор кода и рецензент согласны в том, что нет разумной вероятности, что код будет неверно истолкован без скобок, и при этом скобки не облегчили бы его чтение. Нет причины полагать, что каждый, кто читает код, помнит наизусть всю таблицу приоритетов использования операторов Java.
4.8 Особые конструкции
4.8.1 Классы-перечисления
После каждой запятой, которая следует за константой перечисления, разрыв строки необязателен. Дополнительные пустые строки (обычно только одна) также допускаются. Вот пример такого кода:
private enum Answer {
  YES {
    @Override public String toString() {
      return "yes";
    }
  },

  NO,
  MAYBE
}
Код класса-перечисления без методов и комментариев, описывающих его константы, может быть представлен, как если бы это был инициализатор массива (см. Раздел 4.8.3.1, Инициализаторы массивов).
private enum Suit { CLUBS, HEARTS, SPADES, DIAMONDS }
Так как перечисления - это классы, для них следует применять все прочие правила для представления классов.
4.8.2 Объявления переменных
4.8.2.1 Одна переменная на одно объявление
Каждая переменная (как поля, так и локальная переменная) объявляется только по одной за раз: такие объявления, как int a, b; не используются.

Исключение: Множественные объявления переменных допускаются в заголовке цикла for.
4.8.2.2 Объявлены тогда, когда это нужно
Локальные переменные не обязательно объявляются в начале блока или блочной конструкции. Наоборот, локальные переменные объявляются непосредственно там, где они впервые обоснованно используются, чтобы минимизировать область их действия. Обычно у локальных переменных есть инициализаторы, или же они инициализируются сразу после объявления.
4.8.3 Массивы
4.8.3.1 Инициализаторы массивов могут быть «блочными»
Любой массив может быть инициализирован так, как если бы он был блочной конструкцией. К примеру, весь следующий код допустим (список примеров не полный):
new int[] {           new int[] {
  0, 1, 2, 3            0,
}                       1,
                        2,
new int[] {             3,
  0, 1,               }
  2, 3
}                     new int[]
                          {0, 1, 2, 3}
4.8.3.2 Никаких объявлений массивов в стиле языка С
Квадратные скобки ставятся после типа, а не после переменной: String[] args, а не String args[].
4.8.4 Оператор switch
Терминология

Внутри блока switch располагается одна или более группа выражений. Каждая группа выражений состоит из одного или более указателей блока switch (как case FOO:, так и default:), за которым следует одно или более выражений (или, в случае последней группы выражений, ни одного выражения или более).
4.8.4.1 Смещение
Как и в случае с любым другим блоком, содержимое блока switch смещается на 2 пробела.

После указателя блока switch делается перенос строки, а смещение увеличивается на 2 пробела, так же как при открытии блока. Каждый следующий указатель блока switch возвращается на предыдущий уровень смещения, как при закрытии блока.
4.8.4.2 Провал комментируется
Внутри блока switch каждая группа выражений либо завершается переходом (с помощью операторов break, continue, return или выбросом исключения), либо помечается комментарием, чтобы обозначить, что выполнение кода будет или может быть продолжено в следующей группе выражений. Достаточно любого комментария, передающего идею провала (обычно // fall through). Такой особый комментарий не требуется в в последней группе выражений блока switch. Пример:
switch (input) {
  case 1:
  case 2:
    prepareOneOrTwo();
    // fall through
  case 3:
    handleOneTwoOrThree();
    break;
  default:
    handleLargeNumber(input);
}
Обратите внимание, что комментарий требуется не после case 1:, а лишь в конце группы выражений.
4.8.4.3 Указатель default присутствует
Каждый блок switch содержит группу выражений default, даже если она не содержит кода.

Исключение: Блок switch для типа enum может быть без группы выражений default, если он содержит явные случаи, охватывающие все возможные значения этого типа. Это позволяет инструментальной среде разработчика или другим инструментам статического анализа вызвать предупреждение о том, что некоторые случаи не охвачены.
4.8.5 Аннотации
Аннотации применяемые к классу, методу или конструктору, следуют непосредственно после блока документации, и каждая аннотация указывается на собственной строке (то есть по одной аннотации на строку). Эти разрывы строки не являются переносами строки (Раздел 4.5, Перенос строки), поэтому уровень отступа не увеличивается. Пример:
@Override
@Nullable
public String getNameIfPresent() { ... }
Исключение: Вместо этого одиночная аннотация без параметров может отображаться вместе с первой строкой сигнатуры, например:
@Override public int hashCode() { ... }
Аннотации, применяемые к полю, также появляются сразу после блока документации, но в этом случае несколько аннотаций (возможно, параметризованных) могут быть перечислены в одной строке, например:
@Partial @Mock DataLoader loader;
Не существует особых правил для форматирования аннотаций к параметрам, локальным переменным или типам.
4.8.6 Комментарии
Этот раздел посвящен комментариям реализации. Javadoc рассматривается отдельно в Разделе 7, Javadoc.

Любому разрыву строки может предшествовать произвольное количество пробелов, за которым следует комментарий реализации. Такой комментарий делает строку непустой.
4.8.6.1 Стиль блочного комментария
Уровень отступа блочного комментария совпадает с окружающим кодом. Блочные комментарии могут быть как вида /* ... */ , и так и вида // ... . Для многострочных комментариев вида /* ... */ последующие строки должны начинаться с символа *, выравненного с символом * с предыдущей строки.
/*
 * This is          // And so           /* Or you can
 * okay.            // is this.          * even do this. */
 */
Комментарии не заключаются в прямоугольники, изображенные звездочками или другими символами.
При написании многострочных комментариев, используйте стиль /* ... */, если хотите, чтобы средства автоматического форматирования кода делали перенос строки при необходимости (в стиле параграфов). Большинство средств форматирования могут делать этого с блоками комментариев в стиле // ....
4.8.7 Модификаторы
Модификаторы класса и членов, если они присутствуют, отображаются в порядке, рекомендованном Спецификацией языка Java:
public protected private abstract default static final transient volatile synchronized native strictfp
4.8.5 Аннотации
Целочисленные литералы типа long используют прописные буквы L, а не строчные (чтобы не перепутать с цифрой 1). Например, 3000000000L вместо 3000000000l.
Оригинал руководства Google Java Style Guide