1. 개요
이 문서는 Java™ 프로그래밍 언어의 소스 코드에 대한 Google의 코딩 표준에 대한 완전한 정의를 제공한다. 특정 소스 파일이 이 규칙을 준수할 경우 Google 스타일로 작성된 파일로 간주된다.
다른 프로그래밍 스타일 가이드처럼, 이 문서에서는 형식적 문제뿐만 아니라 다양한 규약 및 코딩 표준도 다룬다. 그러나 이 문서는 주로 모든 경우에 적용될 수 있는 엄격한 규칙에 중점을 두며, 인간이나 도구로 강제할 수 없는 조언은 피하려고 한다.
1.1 용어 노트
이 문서에서는 특별히 명시되지 않는 한:
- class: "일반적인" 클래스, 열거형 클래스, 인터페이스 또는 애너테이션 타입(@interface)을 모두 포함하는 의미로 사용된다.
- member(클래스의 멤버): 중첩 클래스, 필드, 메서드 또는 생성자를 포함하는 포괄적인 의미로 사용된다. 즉. 이니셜라이저나 주석을 제외한 클래스의 모든 상위 콘텐츠를 포함한다.
- comment(주석): 항상 구현 주석을 의미하며, "documentation comments"라는 표현은 사용하지 않고 일반적으로 Javadoc이라고 부른다..
- 다른 용어 노트는 문서 전반에 걸쳐 필요할 때마다 나타난다.
1.2 가이드 노트
이 문서에 나오는 예제 코드는 규범적이지 않다. 즉, 예제는 Google 스타일을 따르지만, 코드르 표현하는 유일한 방법을 나타내지는 않는다. 예제에서 사용된 선택적 형식은 규칙으로 강제하지 않아야 한다.
2. 소스 파일 기본 사항
2.1 파일 이름
소스 파일 이름은 대소문자를 구분하며, 상위 클래스의 이름과 `.java` 확장자로 이루어진다.
2.2 파일 인코딩: UTF-8
소스 파일은 UTF-8로 인코딩된다.
2.3 특수 문자
2.3.1 공백 문자
줄 종결자 시퀀스를 제외하고, ASCII horizontal space character(0x20)는 소스 파일의 어디에서나 사용할 수 있는 유일한 공백 문자이다. 이는 다음을 의미한다.
- 문자열 및 문자 리터럴 내의 모든 다른 공백 문자는 이스케이프 처리된다.
- 들여쓰기에 Tab은 사용되지 않는다.
2.3.2 특수 이스케이프 시퀀스
특수 이스케이프 문자들(`\b`, `\t`, `\n`. `\f`, `\r`, `\"`, `\'` 및 `\\`)은 해당 시퀀스가 사용되며, 8진수(ex. \012)나 유니코드(ex. \u000a) 이스케이프 대신 사용된다.
2.3.3 Non-ASCII 문자
Non-ASCII 문자의 경우 실제 유니 코드 문자 (ex. ∞) 또는 해당 유니코드 이스케이프(ex. \u221e)가 사용된다. 선택은 코드의 가독성과 이해도를 높이는 데 무엇이 도움이 되는지에 따라 결정된다. 그러나 문자열 리터럴 및 주석 외부에서 유니코드 이스케이프는 강력히 권장되지 않는다.
tip: 유니코드 이스케이프나 실제 유니코드 문자를 사용할 경우, 설명 주석이 매우 유용할 수 있다.
Example | Discussion |
`String unitAbbrev = "μs";` | 최고 : 주석이 없이도 완벽하게 명확함. |
`String unitAbbrev = "\u03bcs"; // "μs"` | 허용되지만 굳이 이럴 필요 없음. |
`String unitAbbrev = "\u03bcs"; // Greek letter mu, "s"` | 허용되지만 어색하고 실수할 가능성이 있음. |
`String unitAbbrev = "\u03bcs";` | 나쁨 : 읽는 사람이 알 수 없음. |
`return '\ufeff' + content; // byte order mark` | 좋음 : 비인쇄 문자는 이스케이프 처리하고, 주석을 추가할 수 있음. |
tip: 일부 프로그램이 Non-ASCII 문자를 올바르게 처리하지 못할까봐 코드의 가독성을 낮추지 말자. 만약 그런 일이 발생하면 그 프로그램이 잘못된 것이며 수정되어야 한다.
3. 소스 파일 구조
소스 파일은 다음과 같은 순서로 구성된다.
- 라이선스 또는 저작권 정보 (있을 경우)
- package(패키지) 문
- 임포트 문
- 상위 클래스 하나
각 섹션 사이에는 정확히 한 줄의 빈 줄이 있다.
3.1 라이선스 또는 저작권 정보(있을 경우)
파일에 라이선스 또는 저작권 정보가 포함되어 있다면, 이 위치에 포함된다.
3.2 패키지 문
패키지 문은 줄바꿈 되지 않는다.
열 제한 (섹션 4.4, 열제한: 100)은 패키지 문에는 적용되지 않는다.
3.3 임포트 문
3.3.1 와일드카드 임포트 없음
와일드 카드 임포트(static 또는 일반)는 사용하지 않는다.
3.3.2 줄 바꿈 없음
임포트 문은 줄 바꿈되지 않는다. 열 제한(섹션 4.4, 열제한: 100)은 임포트 문에 적용되지 않는다.
3.3.3 정렬 및 공백
임포트는 다음과 같은 순서로 정렬된다.
- 모든 static 임포트는 하나의 블록에 모은다.
- 모든 non-static 임포트는 하나의 블록에 모은다.
static 임포트와 non-static 임포트가 모두 있을 경우, 두 블록 사이에 한 줄의 빈 줄을 둔다. 임포트 문 사이에 다른 빈 줄은 없다.
각 블록 내에서 임포트된 이름은 ASCII 정렬 순서대로 나타낸다.
3.3.4 클래스에 대한 static 임포트 없음
static 중첩 클래스를 위해 static 임포트를 사용하지 않는다. 읻르은 일반 임포트로 처리된다.
3.4 클래스 선언
3.4.1 정확히 하나의 상위 클래스 선언
각 상위 클래스는 하나의 소스 파일에 위치한다.
3.4.2 클래스 내용의 순서
클래스의 멤버와 이니셜라이저를 정렬하는 방식은 가독성에 큰 영향을 미칠 수 있다. 그러나 이를 위한 단일 정답은 없으며, 서로 다른 클래스는 서로 다른 방식을 사용할 수 있다.
중요한 점은 각 클래스가 논리적인 순서를 사용하며, 그 이유를 설명할 수 있어야 하다는 것이다. 예를 들어, 새로운 메서드를 항상 클래스의 끝에 추가하지 않는 것이 좋다. 이는 "추가된 날짜 순"이라는 논리적이지 않은 정렬 방식을 초래할 수 있기 때문이다.
3.4.3.1 오버로드: 절대 분리하지 않음
클래스에 여러 생성자 또는 동일한 이름을 가진 여러 메서드가있는 경우 이들은 사이에 다른 코드 없이 순차적으로 나타나야 한다.(private 멤버라 할지라도)
4. Formatting
4.1 중괄호
4.1.1 선택적 중괄호의 사용
중괄호는 `if`, `else`, `for`, `do`, `while`문 또는 body가 비어 있거나 단일 문만 포함된 경우에도 사용한다. 람다 표현식의 중괄호와 같은 다른 선택적 중괄호는 여전히 선택 사항이다.
4.1.2 비어 있지 않은 블록: K&R 스타일
비어있지 않은 블록 및 블록과 유사한 구조체의 중괄호는 K&R(Kernighan and Ritchie) 스타일을 따른다. (일명 이집트식 중괄호)
- 중괄호 앞에 줄 바꿈을 하지 않는다.
- 여는 중괄호 뒤에 줄 바꿈을 한다.
- 닫는 중괄호 앞에 줄 바꿈을 한다.
- 닫는 중괄호 뒤에는 줄 바꿈을 하되, 구문이 끝나거나 메소드, 생성자, 클래스가 끝났을 때 적용된다. 예를 들어, 닫는 중괄호 뒤 `else` 또는 쉼표가 있는 경우에는 줄 바꿈을 하지 않는다.
예외: 이러한 규칙이 세미콜론(`;`)으로 끝나는 단일 문을 허용하는 경우, 문 블록이 나타날 수 있으며, 이 블록의 여느 중괄호는 줄 바꿈이 선행된다. 이러한 블록은 일반적으로 지역 변수를 제한하기 위해 도입된다.
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();
}
{
int x = foo();
frob(x);
}
}
};
4.1.3 빈 블록: 간결하게 작성 가능
빈 블록 또는 블록과 유사한 구조체는 K&R 스타일로 작성할 수 있다. 대안으로는 여느 중괄호와 닫는 중괄호 사이에 아무런 문자나 줄 바꿈 없이 바로 닫을 수 있다(`{}`). 단, 다중 블록 문(여러 블록을 직접 포함하는 `if/else` 또는 `try/catch/finally`등)의 일부가 아닌 경우에 한한다.
예시:
// 허용
void doNothing() {}
// 허용
void doNothingElse() {
}
// 허용되지 않음: 멀티 블럭 구문에서는 간결한 빈 블럭을 사용할 수 없음
try {
doSomething();
} catch (Exception e) {}
4.2 블록 들여쓰기: +2 스페이스
새로운 블록 또는 블록과 유사한 구조체가 열릴 떄마다 들여쓰기는 두 칸씩 증가한다. 블록이 종료되면 들여쓰기는 이전 수준으로 돌아간다. 들여쓰기 수준은 블록 전반에 걸쳐 코드와 주석 모두에 적용된다.
4.3 한 줄에 한 문장
각 문장은 줄 바꿈으로 끝난다.
4.4 열 제한: 100
Java 코드는 100자 열 제한을 따른다. "character"는 유니코드 코드 포인트를 의미한다. 아래에 명시된 예외를 제외하고, 이 제한을 초과하는 줄은 섹션 4.5의 줄 바꿈 규칙에 따라 줄 바꿈해야 한다.
각 유니 코드 코드 포인트는 표시 너비 크기에 상관없이 하나의 문자로 계산된다. 예를 들어, full-width 문자(e.g 중국어, 일본어, 한국어)를 쓴다면 규칙보다 일찍 개행하는게 좋다.
예외:
- 열 제한을 지키는 것이 불가능한 줄(예: Javadoc의 긴 URL 또는 JSNI 메서드 레퍼런스)
- pakcage 및 import 문(섹션 3.2 패키지 문 및 섹션 3.3 임포트 문 참조)
- 쉘에 복사 붙여넣기 되는 커멘드 라인에 대한 주석
- 매우 긴 식별자. 드물지만 필요한 경우에는 열 제한을 초과할 수 있다. 그 경우, 주변 코드의 올바른 줄 바꿈은 google-java-format에 의해 생성된 것처럼 처리된다.
4.5 줄바꿈
한 줄에 법적으로 수용될 수 있는 코드가 여러 줄로 나누는 활동을 "줄 바꿈"이라고 한다.
모든 상황에서 줄을 어떻게 나눌지 결정하는 포괄적인 공식은 없다. 동일한 코드를 줄 바꿈하는 유효한 방법이 여러가지일 수 있다.
tip: 메서드나 지역 변수를 추출하면 줄 바꿈없이 문제를 해결할 수 있다.
4.5.1 줄을 어디에서 나눌지
줄 바꿈의 주요 지침은 더 높은 문법 레벨에서 바꾸는 것이다.
- 줄이 비할당 연산자에서 나뉠 때, 기호 앞에서 이루어진다. (이는 C++ 및 JavaScript와 같은 다른 언어에서 Google 스타일로 사용하는 관행과는 다르다.)
- 이는 다음 "operator-like" 기호에도 적용된다:
- 점(.) 구분자
- 메서드 참조의 두 개의 콜론(::)
- 타입 바운딩의 앰퍼센드 기호 (<T extends Foo & Bar>)
- catch 블럭의 파이프 ( catch (FooException | BarException e) )
- 이는 다음 "operator-like" 기호에도 적용된다:
- 줄이 assignment 연산자에서 나뉠 때, 일반적으로 기호 뒤에서 이루어지지만, 어느 쪽이든 허용된다.
- 이는 향상된 for문(“foreach”)에서 "assignment-operator-like" 콜론에도 적용된다.
- 메서드나 생성자의 이름은 다음에 오는 여는 괄호와 함께 유지된다.
- 쉼표(,)는 앞의 토큰과 함께 유지된다.
- 람다에서 화살표(->)와 인접한 곳에서 줄이 나뉘지 않으며, 단일 중괄호 없는 표현식으로 구성된 람다 본문의 경우 화살표 바로 뒤에서 나눌 수 있다.
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 공백
4.6.1 수직 공백
하나의 빈 줄은 이럴 때 나타난다.
- 연속적인 멤버나 클래스의 초기화: 필드, 생성자, 메소드, 중첩 클래스, 정적 초기화 그리고 인스턴스 초기화
- 예외: 코드가 없는 두 개의 연속된 필드 사이의 빈 줄은 선택 사항이다. 빈 줄은 필드를 논리적으로 그룹화하는 데 필요할 때 사용된다.
- 예외: enum 상수 사이의 빈 줄은 섹션 4.8.1에서 다룬다.
- 이 문서의 다른 섹션에서 요구되는 경우(예: 섹션 3, 소스 파일 구조 및 섹션 3.3, 임포트 문).
하나의 빈 줄은 어디에서든 가독성을 향상시키는 경우에 나타날 수 있다. 예를 들어, 논리적 하위 섹션으로 코드를 구성하기 위해 명령문 사이에 사용될 수 있다. 클래스의 첫 번째 멤버 또는 이니셜라이저 전이나 마지막 멤버 또는 이니셜라이저 후에 빈 줄을 사용하는 것은 권장되지도 않으며 금지되지도 않는다.
다수의 공백 줄은 허용은 되나 요구되지는 않는다.(지양)
4.6.2 수평 공백
리터럴, 주석 및 Javadoc을 제외하고 언어 또는 기타 스타일 규칙이 필요한 곳을 넘어서는 경우 단일 ASCII 공간이 다음 장소에만 나타난다.
- 예약어(`if`, `for`, `catch` 등)와 해당 예약어 뒤에 오는 여는 괄호 사이.
- 예약어(`else`, `catch` 등)와 해당 예약어 앞에 오는 닫는 중괄호 사이.
- 중괄호는 여느 모든 경우에 사용, 예외 2가지
- @SomeAnnotation({a, b}) (공백 없음)
- String[][] x = {{"foo"}}; ({{ 사이에 공백 필요 없음)
- 모든 이항 또는 삼항 연산자 양쪽에 사용. 다음 "operator-like" 기호에도 적용됩니다:
- 앰퍼샌드(&)가 있는 연결형 타입 경계: <T extends Foo & Bar>
- 파이프(|)가 있는 catch 블록: catch (FooException | BarException e)
- 향상된 for문에서의 콜론(:)
- 람다 표현식에서의 화살표(->)
- 하지만 메서드 참조의 두 개의 콜론(::)이나 점(.) 구분자에는 적용되지 않습니다.
- Object::toString
- object.toString()
- 캐스트 뒤 ,:; 또는 닫는 괄호
- // 더블 슬래시에서 양쪽에 사용. 여러 수의 공백이 허용되지만 필수사항은 아니다.
- 선언의 type과 변수 사이 : List list
- (선택 사항) 배열 선언문 괄호 안에 공백: `new int[] {5,6}` 또는 `new int[] { 5, 6 } 둘 다 가능
- type annotation이나 대괄호
이 규칙은 줄의 시작 또는 끝에 추가 공백을 요구하거나 금지하는 것으로 해석되지 않고 내부 공간 만을 다룬다.
4.7 그룹 괄호: 권장됨
선택적 그룹 괄호는 작성자와 검토자가 코드가 없으면 잘못 해석 될 가능성이 없으며 코드를 읽기 쉽게 만든다는 데 동의하지 않는 경우에만 생략된다. 모든 독자가 전체 Java 연산자 우선 순위 테이블을 가지고 있다고 가정하는 것은 합리적이지 않다. 즉, 우선순위 연산자가 명확하더라도 소괄호로 감싸는것을 추천한다는 말이다.
4.8 특정 구문
4.8.1 Enum 클래스
enum 상수 뒤에 오는 각 쉼표 뒤에 줄 바꿈은 선택 사항이다. 추가적인 빈 줄(보통 하나)은 허용된다.
private enum Answer {
YES {
@Override public String toString() {
return "yes";
}
},
NO,
MAYBE
}
메소드와 documentaation이 없는 enum 클래스는 배열 초기화와 같은 포맷으로 작성될 수 있다. (4.8.3.1 배열 초기화 참조)
private enum Suit { CLUBS, HEARTS, SPADES, DIAMONDS }
enum 클래스들은 클래스이므로, 클래스 형식 규칙이 모두 적용된다.
4.8.2 변수 선언
4.8.2.1 한 선언에 하나의 변수
각 변수 선언(필드 또는 로컬)은 하나의 변수만 선언한다. 예를 들어 `int a, b;`와 같은 선언은 사용하지 않는다.
예외: for 문 헤더에서는 여러 변수를 선언할 수 있다.
4.8.2.2 필요한 때에 선언됨
지역 변수는 항상 블록 또는 블록과 유사한 구조체의 시작 부분에서 선언되지 않는다. 대신, 해당 변수가 처음 사용되는 지점에 가깝게 선언되며(합리적인 범위 내에서), 변수의 범위를 최소하한다, 지역 변수 선언에는 일반적으로 초기화가 포함되거나 선언 직후에 초기화된다.
4.8.3 배열
4.8.3.1 배열 이니셜 라이저: "block-like"
배열 초기화는 "block-like construct"처럼 포매팅 될 수 있다. 예를들어 다음과 같은 경우는 모두 가능하다.
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 C 스타일 배열 선언 없음
대괄호는 변수의 일부가 아닌 타입의 일부로 처리된다. `String[] args`가 맞으며, `String args[]`는 틀리다.
4.8.4 Switch 문
switch 블록의 중괄호 안에는 하나 이상의 명령 그룹이 있다. 각 명령 그룹은 하나 이상의 switch 레이블(`case F00:` 또는 `default:`)과 하나 이상의 명령(또는 마지막 명령 그룹의 경우 0개 이상의 명령)으로 구성된다.
4.8.4.1 들여쓰기
다른 블록과 마찬가지로 switch 블록의 내용은 +2로 들여쓰기 된다.
switch 레이블 뒤에는 줄 바꿈이 있으며, 들여쓰기 수준은 +2로 증가한다. 다음 switch 레이블은 이전 들여쓰기 수준으로 돌아간다.
4.8.4.2 Fall-through: 주석 처리
switch 블록 내에서 각 명령 그룹은 갑작스럽게 종료되거나(`break`, `continue`, `return` 또는 발생한 예외) 실행이 다음 명령 그룹으로 계속됨을 나타내는 주석이 있다. fall-through의 개념을 전달하는 모든 주석은 충부하다(일반적으로 `// 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 코드가없는 경우에도 default문 그룹이 포함된다.
예외 : enum 유형에 대한 switch 문은 해당 유형의 가능한 모든 경우를 포함하는 명시적 케이스를 처리한 경우 명령문 그룹을 생략 할 수 있다. 이를 통해 IDE 또는 기타 정적 분석 도구는 누락 된 사례가있는 경우 경고를 발행 할 수 있다.
4.8.5 애노테이션
4.8.5.1 타입 사용 애너테이션
타입 사용 애너테이션은 주석이 붙은 타입 바로 앞에 나타난다. 애너테이션이 @Target(ElementType.TYPE_USE)으로 메타 주석이 달린 경우 이는 타입 사용 애너테이션이다.
final @Nullable String name;
public @Nullable Person getPersonByName(String name);
4.8.5.2 클래스 애너테이션
클래스에 적용되는 애너테이션은 문서 블록 바로 뒤에 나타나며, 각 애너테이션은 별도의 줄에 나타난다(즉, 줄 당 하나의 애너테이션). 이러한 줄 바꿈은 줄 바꿈 규칙(섹션 4.5, 줄 바꿈)에 속하지 않으며, 들여쓰기 수준이 증가하지 않는다.
@Deprecated
@CheckReturnValue
public final class Frozzler { ... }
4.8.5.3 메서드 및 생성자 애너테이션
메서드 및 생성자 선언에 대한 애너테이션 규칙은 클래스 애너테이션과 동일하다.
@Deprecated
@Override
public String getNameIfPresent() { ... }
예외: 파라미터가 없는 애너테이션 하나는 시그니처의 첫 번째 줄과 함께 나타날 수 있다.
@Override public int hashCode() { ... }
4.8.5.4 필드 애너테이션
필드에 적용되는 애너테이션도 문서 블록 바로 뒤에 나타나며, 이 경우 매개변수가 있는 여러 애너테이션이 한 줄에 나열될 수 있다.
@Partial @Mock DataLoader loader;
4.8.5.5 파라미터 및 로컬 변수 애너테이션
파라미터나 로컬 변수에 대한 애너테이션의 서식을 지정하는 특정 규칙은 없다(물론 애너테이션이 타입 사용 애너테이션인 경우 제외).
4.8.6 주석
이 섹션에서는 구현 주석을 다룬다. Javadoc은 별도로 섹션 7에서 다룬다.
줄 바꿈 앞에는 임의의 공백과 구현 주석이 올 수 있다. 이러한 주석은 행을 공백이 아닌 것으로 렌더링한다.
4.8.6.1 블록 주석 스타일
블록 주석은 주 변 코드와 동일한 레벨에서 들여 쓰기된다. /* ... */ 이나 // ... 의 스타일을 가진다. / * ... */ 여러 줄이면 뒤이어 오는 줄은 *로 시작해야 하는데 그 이전 *과 맞아야 한다.
/*
* This is // And so /* Or you can
* okay. // is this. * even do this. */
*/
주석은 별표 또는 기타 문자로 그려진 박스에 넣지 않는다.
Tip: 여러 줄의 주석을 작성할 때 문단 형식으로 re-wrap을 하고 싶으면 /* ... */ 의 형식으로 작성한다. 대부분 포매터들은 // ... 의 re-wrap을 지원하지 않는다.
4.8.7 접근 제한자
클래스와 멤버의 접근 제한자 목록이다.
public protected private abstract default static final transient volatile synchronized native strictfp
4.8.8 숫자 리터럴
long의 값을 가지는 정수 리터럴은 대문자 L의 접미사를 가진다. (소문자가 아닌 이유는 숫자 1과 헷갈리기 때문).
예를들어 3000000000L을 3000000000l 대신에 쓴다.
5. 네이밍
5.1 모든 식별자에 공통된 규칙
식별자는 ASCII 문자와 숫자만 사용한다. 어떤 경우에는 `_`를 사용하여 표시하기도 한다. 따라서 모든 유효한 식별자 이름은 정규 표현식 `\w+`과 일치한다.
Google 스타일에서는 특수 접두사 또는 접미사가 사용되지 않는다. 예를 들어, 이 이름들은 구글 스타일이 아니다(`name_`, `mName`, `s_name`, `kName`)
5.2 식별자 유형별 규칙
5.2.1 package 이름
패키지 이름은 소문자와 숫자만 사용한다(밑줄X). 연속된 단어는 단순히 이어진다.
예를 들어, `com.example.deepspace`는 맞지만, `com.example.deepSpace` 또는 `com.example.deep_space`는 틀리다.
5.2.2 class 이름
클래스 이름은 UpperCamelCase로 작성된다.
클래스 이름은 일반적으로 명사 또는 명사구이다(ex. `Character` 또는 `ImmutableList`). 인터페이스 이름도 명사 또는 명사구일 수 있지만(ex. `List`), 때로는 형용사 또는 형용사구가 될 수도 있다(ex. `Readable`).
테스트 클래스는 `Test`로 끝나는 이름을 가진다(ex. `HashIntegrationTest`). 단일 클래스를 다루는 경우, 해당 클래스 이름 뒤에 `Test`를 붙여서 이름을 짓는다(ex. `HashImplTest).
5.2.3 method 이름
메소드 이름은 lowerCamelCase로 작성된다,
메서드 이름은 일반적으로 동사 또는 동사구이다(ex. `sendMessage` 또는 `stop`). 언더스코어는 JUnit 테스트에서 논리적 컴포넌트를 분리시키기 위해 각각을 lowerCamelCase로 변경시켜 나올수 있다. 하나의 전형적인 패턴은_ 이다(ex. `pop_emptyStack`). 테스트 메소드를 작성하는 하나의 정확한 방법은 없다.
5.2.4 constant 이름
상수 이름은 CONSTANT_CASE를 사용한다: 모두 대문자로 밑줄(`_`)로 각 단어를 구분한다.
상수는 내용이 완전히 불변하고 메서드에 감지 가능한 부작용이 없는 static final 필드이다. 여기에는 원시타입, 문자열 그리고 불변 타입, 불변타입의 불변 컬렉션이 포함된다.
인스턴스의 상태가 변경될 수 있는 경우, 상수가 아니다. 단순히 객체의 상태 변화를 막는 것이 목적은 아니다.
// Constants
static final int NUMBER = 5;
static final ImmutableList<String> NAMES = ImmutableList.of("Ed", "Ann");
static final ImmutableMap<String, Integer> AGES = ImmutableMap.of("Ed", 35, "Ann", 32);
static final Joiner COMMA_JOINER = Joiner.on(','); // because Joiner is immutable
static final SomeMutableType[] EMPTY_ARRAY = {};
enum SomeEnum { ENUM_CONSTANT }
// Not constants
static String nonFinal = "non-final";
final String nonStatic = "non-static";
static final Set<String> mutableCollection = new HashSet<String>();
static final ImmutableSet<SomeMutableType> mutableElements = ImmutableSet.of(mutable);
static final ImmutableMap<String, SomeMutableType> mutableValues =
ImmutableMap.of("Ed", mutableInstance, "Ann", mutableInstance2);
static final Logger logger = Logger.getLogger(MyClass.getName());
static final String[] nonEmptyArray = {"these", "can", "change"};
5.2.5 상수가 아닌 필드의 이름
상수가 아닌 필드 이름(정적 또는 기타)은 lowerCamelCase로 작성된다. 이러한 이름은 일반적으로 명사 또는 명사구이다(ex. computedValues 또는 `index`).
5.2.6 파라미터 이름
파라미터 이름은 lowerCamelCase로 작성된다. public 메서드에서 한 문자 파라미터 이름은 피해야 한다.
5.2.7 지역 변수 이름
지역 변수 이름은 lowerCamelCase로 작성된다. final, 불변인 경우에도 지역 변수는 상수로 간주되지 않으며 상수 스타일로 기술해서는 안된다.
5.2.8 타입 변수 이름
각 유형 변수는 다음 두 가지 스타일 중 하나로 이름이 지정된다.
- 단일 대문자, 혹은 단일 숫자가 따라올 수 있다. (ex. E, T, X, T2)
- 클래스에 사용되는 형식의 이름(섹션 5.2.2, 클래스 이름 참조) 뒤에 대문자 T(ex. `RequestT, FooBarT)
5.3 카멜 케이스: 정의
영어 구문을 카멜 케이스로 변환하는 방법에는 여러 가지 합리적인 방법이 있을 수 있다. 예를 들어, 약어나 특이한 구성("IPv6" 또는 "iOS")이 있는 경우이다. 이러한 불확실성을 줄이기 위해 Google 스타일에서는 다음과 같은 (거의) 결정론적 체계를 지정한다.
텍스트 형태의 이름에서 시작:
- 구문을 평범한 ASCII로 변환하고 `'`를 제거한다. 예를 들어 "Müller's algorithm"은 "Muellers algorithm"이 된다.
- 이 결과를 단어로 나누고, 공백 및 남아 있는 구두점(일반적으로 하이픈)으로 구분한다.
- 권장 사항: 특정 단어가 일반적으로 카멜 케이스로 나타난다며, 이를 구성 요소로 나누어야 한다. 예를 들어, "AdWords"는 "ad words"로 나눈다.
- 이제 모든 것을 소문자로 바꾸고, 첫 번째 문자는 다음 규칙에 따라 대문자로 만든다.
- 각 단어는 UpperCamelCase가 되고
- 첫 단어를 제외한 나머지는 lowerCamelCase가 된다.
- 마지막으로 모든 단어를 하나로 조합한다.
텍스트 형태 | 맞음 | 틀림 |
"XML HTTP request" | `XmlHttpRequest` | `XMLHTTPRequest` |
"new customer ID" | `newCustomerId` | `newCustomerID` |
"inner stopwatch" | `innerStopwatch` | `innerStopWatch` |
"supports IPv6 on IOS?" | `supportsIpv6OnIos` | `supportsIPv6OnIOS |
"YouTube importer" | `YouTubeImporter`, `YoutubeImporter`* |
*는 권장되지 않는다.
6. 프로그래밍 관행
6.1 @Override: 항상 사용
@Override는 가능한 모든 경우에 사용해야 한다.
여기에는 슈퍼 클래스 메소드를 재정의하는 클래스 메소드, 인터페이스 메소드를 구현하는 클래스 메소드, 슈퍼 인터페이스 메소드를 재지정하는 인터페이스 메소드가 포함된다.
예외: 부모 메서드가 @Deprecated인 경우 @Override는 생략할 수 있다.
6.2 Caught exceptions: 무시되지 않음
아래에 언급된 경우를 제외하고 예외에 대한 응답으로 아무것도 하지 않는 것은 매우 드물다.
(일반적인 응답은 로그에 기록하거나 "불가능"하다고 판단되면 AssertionError로 다시 던져준다.)
catch 블록에서 아무 조치도 취하지 않는 것이 진정으로 적절할 때 이것이 정당화되는 이유는 주석에 설명되어야 한다.
try {
int i = Integer.parseInt(response);
return handleNumericResponse(i);
} catch (NumberFormatException ok) {
// it's not numeric; that's fine, just continue
}
return handleTextResponse(response);
예외 : 테스트에서 예외를 잡는 부분은 expected, 혹은 expected로 시작하는 이름을 지으면서 무시할 수 있다. 다음 예제는 테스트에서 예외가 나오는게 확실한 상황에서 사용되는 대중적인 형식으로 주석이 필요가 없다.
try {
emptyStack.pop();
fail();
} catch (NoSuchElementException expected) {
}
6.3 static members: 클래스를 사용하여 정규화
static 클래스 멤버에 대한 참조는 클래스 이름으로 수식되며, 해당 클래스의 타입 참조나 표현식으로 수식되지 않는다.
Foo aFoo = ...;
Foo.aStaticMethod(); // good
aFoo.aStaticMethod(); // bad
somethingThatYieldsAFoo().aStaticMethod(); // very bad
6.4 Finalizers: 사용되지 않음
`Object.finalize`을 재정의하지 말자. Finalization은 제거될 예정이다.
7. Javadoc
7.1 Formatting
7.1.1 일반 형식
Javadoc 블록의 기본 형식은 다음 예와 같다.
/**
* 여러 줄로 된 Javadoc 텍스트는 여기에 작성되며,
* 일반적으로 래핑된다.
*/
public int method(String p1) { ... }
또는 다음 단일 줄 형식의 예시:
/** 특별히 짧은 Javadoc. */
기본 형식은 언제나 허용된다. 단일 줄 형식은 전체 Javadoc 블록(주석 마커 포함)이 한 줄에 들어갈 수 있을 때 대체할 수 있다.
7.1.2 문단
단락 사이에는 하나의 빈 줄이 나타난다. 간 단락의 첫 번째 단어 앞에는 `<p>`가 즉시 나타나며, 그 뒤에 공백이 없다.
7.1.3 블록 태그
표준 블록 태그는 @param, @return, @throws, @deprecated 순서로 나타난다. 블록 태그가 여러 줄로 이어질 경우, 이어지는 줄은 네 칸 이상의 들여쓰기를 해야한다.
7.2 요약 구문
각 Javadoc 블록은 짧은 요약 구문으로 시작됩니다. 이 구문은 매우 중요하다. 이는 클래스 및 메서드 인덱스와 같은 특정 컨텍스트에서 나타나는 유일한 부분입니다.
이 구문은 단편적인 구문이며, 완전한 문장이 아니다. "A Foo is a..."나 "This method returns..."와 같이 시작하지 않으며, "Save the record."처럼 완전한 명령문을 형성하지도 않는다. 그러나 이 구문은 마치 완전한 문장인 것처럼 대문자로 시작하고 구두점으로 끝난다.
Tip: 주로 하는 실수: /** @return the customer ID / 이것은 잘못 되었고 /* Returns the customer ID. */로 바뀌어야 한다.
7.3 Javadoc이 사용되는 곳
최소한, Javadoc은 모든 public 클래스와 해당 클래스의 public 또는 protected 멤버에 사용된다.
7.3.1 예외: self-explanatory members
javadoc는 간단하고 명료한 메소드(ex. `getFoo`)에 대해서는 선택 사항이다. 이 경우는 foo를 반환한다 이외에는 도저히 설명할 길이 없는 경우다.
중요: 독자가 알아야 할 관련 정보를 생략하는 것을 안된다. 예를 들어, getCanonicalName의 경우 독자가 "Canonical Name"이라는 용어가 무엇을 의미하는지 모를 수도 있다.
7.3.2 예외: overrides
Javadoc은 슈퍼 타입 메소드를 오버라이드 하는 메소드에 항상 존재하는 것은 아니다.
7.3.4 필수가 아닌 Javadoc
다른 클래스와 멤버는 필요하거나 원하는대로 Javadoc이 있다 .
구현 주석이 클래스 또는 멤버의 전체적인 목적이나 동작을 정의하는 데 사용될 때마다 해당 주석은 대신 Javadoc로 작성됩니다 (/** 사용).
필수가 아닌 Javadoc은 섹션 7.1.2, 7.1.3 및 7.2의 형식화 규칙을 따르도록 엄격하게 요구되지는 않지만 권장된다.
'Java' 카테고리의 다른 글
객체 지향 프로그래밍(Object-Oriented Programming, OOP) (0) | 2024.10.26 |
---|---|
[JUnit] @Parameterized Test (0) | 2024.10.26 |
[Java/김영한] 패키지 (1) | 2024.09.08 |
[Java/김영한] 생성자 (1) | 2024.09.08 |
[Java/김영한] 객체 지향 프로그래밍 (0) | 2024.09.07 |