기억의 저장소
Google Java Style Guide 정리 본문
Google Java Style Guide는 Java를 작성할때 어떤 스타일로 작성하면 좋을지에 대해 작성해놓은문서입니다.
왜 이런 문서를 만들어 놓았을까요?
제 생각은 코드를 보는데 편안해지며 이로 인해 다른 사람이 봐도 편안한 코드가 생성되므로 협업이란 방식으로 돌아가는 프로그래밍 세계에서 꼭 필요하므로 작성해 놓았다 생각합니다.
다른 사람이 봐도 편안한 코드는 Java 코드의 가독성과 일관성을 높이기 위해 사용됩니다. 모든 개발자가 동일한 스타일로 코드를 작성하고, 코드 구성이 일관되며 혼란스럽지 않도록 합니다. 이러한 규칙을 따르면 코드를 읽고 유지보수하기 쉬워지며, 다른 사람과 협업할 때 코드의 일관성을 유지하는 데 도움이 됩니다.
https://google.github.io/styleguide/javaguide.html
위 문서를 보고 번역하며 하나하나 습득하려 노력하였습니다.
모든것을 번역하지 않았고 제 생각만의 번역이 들어가 있는게 있으며 특정 초반 몇개는 제외 되있습니다.
만약 틀린부분이 있다면 댓글 남겨주시면감사하겠습니다.
이것은 권장사항일뿐 정답이 아닙니다. 자기의 스타일 그리고 회사의 스타일에 맞게 필요한 부분을 추려내어 적용하는것에 도움이 되었으면 좋겠습니다.
1. 소개
1.1 용어 참고 사항
- 클래스라는 용어는 일반적인 클래스 , Eum 클래스, 인터페이스 , 어노테이션 타입을 포괄합니다.
- 클래스의 멤버라는 용어는 중첩된 클래스, 필드 , 메서드 , 생성자를 의미하기 위해 포괄적으로 사용됩니다.
즉 initializers 와 주석을 제외한 최상위 컨텐츠입니다. - 주석이라는 용어는 항상 구현 주석을 나타내며, 문서주석 대신 Javadoc이라는 용어를 사용합니다.
implementation comments(구현주석)는 구현한 코드를 설명하기 위한 주석이라고합니다.
documentation comments(문서 주석) API문서화를 위한 주석이라고 합니다.
"block-like construct"는 코드 블록과 유사한 구조를 나타내는 용어입니다. 코드 블록은 중괄호 {}로 둘러싸인 코드 영역을 의미하며, 이와 비슷한 형태를 가진 구조들도 "block-like construct"로 분류됩니다.
"block-like construct"는 중괄호로 둘러싸인 구조들을 일반적으로 가리키는 용어
메서드
public void myMethod() {
// 메서드 본문도 block-like construct
statement1;
statement2;
}
생성자
public MyClass() {
// 생성자 본문도 block-like construct
statement1;
statement2;
}
클래스 초기화 블록
public class MyClass {
// 인스턴스 초기화 블록도 block-like construct
{
statement1;
statement2;
}
// 정적 초기화 블록도 block-like construct
static {
statement3;
statement4;
}
}
람다 표현식 바디
MyInterface myLambda = () -> {
// 람다 표현식의 바디도 block-like construct
statement1;
statement2;
};
2. 소스파일 기본 사항
2.1 파일명
- 소스 파일 이름은 포함 된 최상위 클래스의 대소 문자 구분 이름과 .java확장자로 구성됩니다.
예를 들어, MyClass라는 이름의 최상위 클래스를 포함하는 Java 소스 파일은 MyClass.java로 저장되어야 합니다
2.3 특수문자
2.3.1 공백문자
줄 끝내기 문자(\n)를 제외하고, ASCII horizontal space character (0x20) 은 소스파일에 나오는 유일한 공백 문자이며 이것은 다음을 암시합니다.
- 문자열과 문자 내에서 다른 모든 공백 문자들은 이스케이프 됩니다. (밑 설명 참조)
- Tab은 들여쓰기에 사용되지 않는다. Java의 코딩 스타일 가이드에서는 스페이스를 들여쓰기에 사용하는 것을 권장한다고 합니다.
"이스케이프(escape)되어야 한다"는 표현은 특정한 문자나 문자열을 코드 내에서 표현하거나 나타내기 위해 추가적인 특수한 표기법을 사용해야 함을 의미합니다. 이스케이프 시퀀스는 역슬래시(\) 다음에 특정 문자나 숫자 등을 사용하여 이러한 추가적인 의미를 나타내게 됩니다. 문자열 및 문자 리터럴 내에서 다른 공백 문자가 "이스케이프되어야 한다"는 것은 문자열이나 문자 안에 일반적으로 사용되지 않는 특수 문자(예: 탭, 새 줄, 따옴표 등)를 나타내기 위해 이스케이프 시퀀스를 사용해야 함을 의미합니다. 이렇게 하면 문자 그대로 해석되지 않고, 특별한 의미로 해석됩니다. ( \t는 탭 문자를 나타내며, \n은 줄 끝내기 문자를 나타냅니다. \"는 문자열 내에서 따옴표 문자를 나타냅니다.)
2.3.2 특수 이스케이프 문자들
특수 이스케이프 문자들 (\b, \t, \n, \f, \r, \", \' and \\)은 해당 옥텟(\012) 이나 유니코드(\u000a) 이스케이프 대신에 해당 문자가 사용된다.
유니코드(\u000a) 는 \n을 의미하는데 유니코드(\u000a) 를 사용하는대신에 \n를 쓰라는 의미입니다
2.3.3 Non-ASCII 문자들
ASCII문자가아닌 문자는 유니코드문자나 유니코드와 동등한 이스케이프 문자가 사용된다고 합니다.
코드의 가독성과 이해를 위해 Non-ASCII 문자의 표현 방식을 선택할 때는 어떤 방식이 코드를 더 읽기 쉽고 이해하기 쉽게 만드는지에 따라 결정합니다.
주석이나 문자열 리터럴 외부에서 유니코드 이스케이프를 사용하는 것은 강력히 권장되지 않습니다. 코드의 가독성을 저해할 수 있으므로 이러한 사용은 피해야 합니다.
예 | 논의 |
String unitAbbrev = "μs"; | 최고: 코멘트 없이도 완벽하게 명확합니다. |
String unitAbbrev = "\u03bcs"; // "μs" | 허용되지만 그렇게 할 이유가 없습니다. |
String unitAbbrev = "\u03bcs"; // Greek letter mu, "s" | 허용되지만 어색하고 실수하기 쉽습니다. |
String unitAbbrev = "\u03bcs"; | 나쁨: 독자는 이것이 무엇인지 전혀 모릅니다. |
return '\ufeff' + content; // byte order mark | 좋음: 인쇄할 수 없는 문자에는 이스케이프를 사용하고 필요한 경우 주석을 추가합니다. |
Java 소스 코드에서 ASCII 문자 집합을 벗어나는 문자(즉, 비-ASCII 문자)를 다룰 때 사용되는 내용을 설명하고 있습니다. 이러한 비-ASCII 문자는 주로 유니코드 문자 집합에 속하며, 특수한 문자를 나타내거나 다국어 문자를 표현하는 데 사용됩니다.
3 소스 파일 구조
- License or copyright information, if present 라이센스
- Package statement 패키지
- Import statements import한것들
- Exactly one top-level class 최상위 클래스
Exactly one blank line separates each section that is present. 각 섹션을 나눌때 한줄의 라인을 띄우라 권장합니다.
3.3 임포트 구문
3.3.1 와일드 카드로 import 하지마라
와일드 카드 임포트, static import 같은 것들은 사용하지 않는다.
와일드 카드는 import java.util.*; 와같이 * 을 말합니다. (import static java.lang.Math.*;)
와일드카드 임포트는 가독성을 떨어뜨리고 코드 내에서 사용된 클래스의 출처를 명확하게 파악하기 어렵게 만들 수 있습니다.
3.3.3 순서 및 간격
임포트는 다음과 같은 단계를 따른다:
- 하나의 블럭안에 static 임포트 포함
- 하나의 블럭안에 non-static 임포트 포함
만약에 static과 non-static이 둘 다 있다면, 개행을 하고 두 개의 블럭으로 나눈다. 그 이외에는 개행이 있으면 안되며
각 블록 내에서 임포트 된 이름은 ASCII 정렬 순서로 나열됩니다.
(Note: this is not the same as the import statements being in ASCII sort order, since '.' sorts before ';'.)
임포트 구문에서 정렬은아스키에서 정렬 순서와 동일하지 않을 수 있다는거 같습니다. 이유는 .이라 하는데 잘 모르겠내요
3.3.4 static 중첩 클래스에 static 임포트 하지마라
static 임포트는 static 중첩 클래스에 사용되지 않으며 그것들은 일반적인 임포트를 사용합니다.
정적 임포트는 클래스의 정적 멤버(정적 메서드, 정적 필드 등)를 클래스 이름 없이 사용할 수 있게 해주는 기능입니다. 그러나 정적 중첩 클래스는 클래스 이름을 통해 외부 클래스 내부에서 사용되므로, 정적 임포트를 사용할 필요가 없습니다.
import com.example.OuterClass;
OuterClass.NestedStaticClass nested = new OuterClass.NestedStaticClass();
위와같이 하지말고 아래와 같이 쓰라는것 같다.
import com.example.OuterClass.NestedStaticClass;
NestedStaticClass nested = new NestedStaticClass();
3.4 클래스
3.4.2 클래스 컨텐츠의 순서
중요한 것은 각 클래스가 요청 시 관리자가 설명할 수 있는 논리적 순서를 사용 해야한다는 것입니다. 예를 들어, 새 메서드는 습관적으로 클래스 끝에 추가되지 않습니다. 그렇게 하면 논리적 순서가 아닌 "추가된 날짜별 연대순" 순서가 생성되기 때문입니다.
3.4.2.1 Overloads를 분할하지마라
클래스가 여러개의 생성자들 혹은 같은 이름의 함수들을 가지고 있다면 이것들은 다른 코드들 없이 차례로 나타나야 한다. (static or private 멤버라 할 지라도)
4. Formatting ( 서식 지정)
4.1 괄호
4.1.1 선택적 중 괄호( {} ) 사용
중 괄호는 if, else, for, do, while 구문에 쓰이는데 몸체가 없거나 한 줄의 구문에도 중괄호가 쓰인다.
단 람다 표현식과 같이 다른 상황에서는 중괄호가 선택적으로 사용될 수 있습니다.
Runnable runnable = () -> System.out.println("Hello, Lambda!");
4.1.2 비어있지 않은 블럭
괄호는 비어있지 않은 블럭과 block-like construct에서 Kernighan과 Ritchie 스타일(Egyptian brackets)을 따른다.
- 여는 중괄호에 대한 줄바꿈 : 여는 중괄호 앞에는 줄바꿈이 오지 않으며 뒤에 바로 줄바꿈이 수행됩니다.
- 닫는 중괄호에 대한 줄바꿈 : 닫는 중괄호 전에 줄바꿈을 추가하며 다음에도 줄바꿈을 추가합니다.
단 else 또는 ,가 뒤에오는경우 중괄후 뒤에는 줄바꿈이 없습니다.
"Kernighan and Ritchie style"은 C 프로그래밍 언어의 창시자인 Brian Kernighan과 Dennis Ritchie의 이름을 딴 것으로, 코드를 간결하고 가독성 있게 작성하기 위한 방식으로 유명합니다. "Egyptian brackets"는 중괄호의 모양이 피라미드의 모습과 유사하다는 의미로 사용되며, 코드 블록이나 구조를 중괄호 안에 정렬하는 스타일을 나타냅니다
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();
}
}
};
예외가 있다고하는데
예외가 있다고하는데
String message = "It's Monday!";
System.out.println(message);
위와같이 ; 로 끝나는 문장들은 굳이 {} 를 하지 않으나 아래와같이 switch 문에서
중복 변수선언이 되는경우 {}를 선언하지 않으면 문제가 발생하므로 {}를 선언해준다고합니다.
그냥 그렇다하고 넘어가야징..
switch (dayOfWeek) {
case 1: {
String message = "It's Monday!";
System.out.println(message);
break;
}
case 2: {
String message = "It's Tuesday!";
System.out.println(message);
break;
}
// 이하 생략
}
4.1.3 비어있는 블럭은 간결하게
빈 블럭이나 block-like construct 에서는 { } 괄호 안에 문자가 없거나 줄바꿈이라면 열자마자 끝날 수 있다. 하지만 멀티 블럭 구문에서는 할 수 없다.
// This is acceptable
void doNothing() {}
// This is equally acceptable
void doNothingElse() {
}
멀티블록 catch 부분 저렇게 하지말라하는
// This is not acceptable: No concise empty blocks in a multi-block statement
try {
doSomething();
} catch (Exception e) {}
4.2 블럭 들여쓰기 +2 스페이스
새로운 블럭이나 block-like construct가 열리면 들여쓰기는 스페이스 2번의 공간을 차지합니다. 블럭이 끝나면, 들여쓰기는 이전의 들여쓰기 단계로 돌아가며 들여쓰기 단계는 코드와 주석에 모두 적용됩니다.
우아한테크코스에서는 +4의 수준을 적용합니다.
if (condition1) {
statement1; << 이부분이 +2 스페이스로 들여쓰기 되었다는거
statement2;
} else {
statement3;
} << 블록 종료시 들여쓰기 감소
들여쓰기는 코드의 계층 구조를 시각적으로 표현하기 위한 방법으로, 코드가 어디에 속해 있는지와 블록이 어떻게 중첩되어 있는지를 쉽게 파악할 수 있게 도와줍니다.
4.3 줄당 하나의 서술
하나의 구문은 줄바꿈이 뒤따라야합니다.
String A = 1; <<이뒤에 바로 줄바꿈이 이어져야한다는 뜻입니다.
String B = 2;
4.4 열 제한 100줄
Java 코드의 열 제한은 100자입니다. "문자"는 모든 유니코드를 의미합니다.
예외
- 열 제한을 준수할 수 없는 경우 (예를들어, Javadoc의 긴 URL 혹은 긴 JSNI 메서드 레페런스)
- package 나 import 구문들 (3.2 패키지 구문, 3.3 임포트 구문 참조)
- 쉘에 복사 붙여넣기 되는 커멘드 라인에 대한 주석
- 매우 긴 식별자가 필요한 특별한 경우에는 100자 제한을 넘어설 수 있습니다.
이 경우에는"google-java-format"이라는 도구를 활용하여 코드의 형식을 자동으로 정리하고 줄 바꿈 스타일을 설정하는 것을 권장합니다.
4.5 줄바꿈
코드를 하나의 줄에서 여러 줄로 나눌 때이 작업을 줄 바꿈 이라고 합니다 .
모든 상황에서 줄 바꿈하는 방법을 정확히 보여주는 공식은 없으며 동일한 코드를 줄 바꿈하는 여러 가지 유효한 방법이 많이 있습니다.
참고 : 줄 바꿈의 일반적인 이유는 열 제한을 초과하지 않도록하는 것이지만 실제로 열 제한에 맞는 코드도 작성자의 재량에 따라 줄 바꿈 될 수 있습니다.
💡 Tip : 메서드 또는 지역 변수를 추출하면 줄 바꿈없이 문제를 해결할 수 있습니다.
4.5.1 줄바꿈 위치
언제 줄을 바꿔야하나?
코드를 줄 바꿈하는 경우에 있어서 높은 문법 수준에서 줄 바꿈을 선호해야 한다는 원칙
("높은 문법 수준(higher syntactic level)"은 프로그래밍 코드를 더 큰 논리적 단위로 구조화하거나 나누는 것을 의미합니다.)
낮은 문법 수준 예시:
if (condition1)
if (condition2)
statement;
높은 문법 수준 예시:
if (condition1 && condition2) {
statement;
}
높은 문법 수준의 코드는 논리적인 단위를 보다 명확하게 표현하고 있습니다.
중첩된 if 문을 &&를 이용해 논리적인 블록을 만들면, 코드의 구조와 의미가 더 잘 드러나게 됩니다.
코드의 문법 수준은 들여쓰기(indentation)와 블록 구조(block structure) 등으로 표현됩니다.
들여쓰기와 블럭 구조를 잘 표현해서 높은 수준의 코드를 만들어야할듯
if (condition1 && condition2 || condition3 && condition4 || condition5) {
// code
}
if ((condition1 && condition2) <<구조화
|| (condition3 && condition4)
|| condition5) {
// code
}
methodName(parameter1, parameter2, parameter3,
parameter4, parameter5);
또한
- non-assignment 연산자에서 줄 바꿈이 일어날 경우 바꿈은 기호 이전에 위치한다. ( non-assignment operator는 값을할당하지 않는 연산자 ex) 논리 &&, 비교연산자 == ) 그리고 아래와 같은 operator like 기호에도 적용됩니다.
- 마침표 분리자(.)
- 메서드 참조의 두 개의 콜론(::)
- 타입 바운드에서의 ampersand(&) (<T extends Foo & Bar>)
- catch 블록에서의 파이프 (catch (FooException | BarException e)).
someObject
.method()
.anotherMethod();
int result =
num1 + num2
+ num3 + num4
&& condition1 && condition2;
(catch (FooException
| BarException e)).
- 할당 연산자(=) 에서 줄이 끊어지면 일반적으로 기호 뒤에 끊어 지지만 어느 쪽이든 허용됩니다.(앞에도 된다는것)
또한 향상된 for문에서도 콜론(:) 에도 적용됩니다 - 메서드나 생성자 이름은 오픈 괄호 ( 와 붙여 씁니다.
SomeClass someInstance = new SomeClass( << ( 는 붙여서 서 써야한다는 의미
);
someInstance.someMethod();
- 쉼표(,)는 이전 토큰과 붙어있게 작성합니다. ex) int a = 5, b = 10, c = 15;
- 람다의 본문이 중괄호가 없는 단일 표현식으로 구성된 경우 화살표 바로 뒤에 줄바꿈이 올 수 있다는 점을 제외하고는 람다의 화살표 근처에서는 줄이 끊어지지 않습니다.
MyLambda<String, Long, Object> lambda =
(String label, Long value, Object obj) -> { << 안끊어짐
...
};
Predicate<String> predicate = str -> 예외
longExpressionInvolving(str);
4.5.2 줄바꿈시 들여쓰기 규칙 ; +4 공백 들여쓰기
코드를 한 줄에서 여러 줄로 나누어 작성해야 할 때, 첫 번째 줄을 제외한 나머지 줄(계속되는 줄)은 최소한 원래 줄에서 +4 만큼 들여쓰기 됩니다. 우아한 테크코스에서는 +8을 권장합니다
연속된 줄이 여러 개인 경우 들여쓰기는 원하는 대로 +4 이상으로 다양할 수 있습니다.
(여러 개의 계속되는 줄이 있을 때, 들여쓰기 수준은 +4 이상으로 조절할 수 있습니다. 즉, 모든 계속되는 줄이 똑같은 들여쓰기 수준을 갖지 않아도 됩니다.)
일반적으로 두 연속 행은 구문적으로 병 요소로 시작하는 경우에만 동일한 들여쓰기 수준을 사용합니다
즉, 두 줄이 비슷한 역할이나 구조를 가지고 있을 때 들여쓰기를 맞춥니다.
예시
int result = someLongExpression
+ anotherLongExpression ( + anotherLongExpression앞에가 들여쓰기 +4되있다는것)
+ yetAnotherLongExpression;
List<String> items = new ArrayList<>();
items.add("item1")
.add("item2")
.add("item3");
4.6 공백
4.6.1 수직 공백
하나의 공백 줄은 항상 이럴 때 나타난다:
- 멤버 또는 초기화 사이에는 단일 빈줄이 나타납니다
예를들어 필드,생성자,메서드,중첩클래스, 정적 초기화 및 인스턴스 초기화 사이에는 빈줄이 들어갑니다.
다만 두개의 연속된 필드 사이에 공백은 선택적이다. 만약 공백을넣는다면 필드의 논리적 그룹으로 나누기 위해 필요할때 사용됩니다.
하나의 공백 줄은 어디에서나 등장할 수 있고, 가독성을 높인다. 예를들어, 코드를 논리적 부분으로 나눌때 쓰인다. 첫 번째 멤버 나 초기화 앞에있는 빈 줄 또는 클래스의 마지막 멤버 나 초기화 뒤에 오는 공백 줄은 권장되거나 권장되지 않는다. - 다수의 공백줄을 허용되나 권장 되지 않습니다.
4.6.2 수평 공백
코드 내에서 필요한 경우나 언어의 요구 사항이나 다른 스타일 규칙을 준수해야 할 때를 제외하고, 또한 리터럴(literals), 주석(comments), 자바독(Javadoc)을 제외한 상황에서 ASCII 공백(space)를 사용해야 하는 위치에 대해 언급하고 있습니다
즉, 이 문장은 특정한 코드 상황에서만 ASCII 공백(space)를 사용하는 경우에 대한 가이드라인을 설명하는 것입니다.
- 예약어(if, for, catch)와 괄호 사이에 공백 ex) if () < if와 ( 사이에 공백
- 닫힌 중괄호와 예약어 사이의 공백
if (condition) {
// code
} else { << 여기 말하는거 } 닫힌 중괄호 else 예약어
// code
}
try {
// code
} catch (Exception e) {
// code
}
- 여는 중괄호 앞에 공백 ex) int[] a = { << 여기에서 =와 { 사이에 공백
- 아래는 예외적인 상황
- @SomeAnnotation({a, b}) (no space is used)
- String[][] x = {{"foo"}}; (no space is required between {{, by item 9 below)
- 이항 또는 삼항 연산자 양쪽에 사용. 이것은 연산자와 유사한" 기호들에도 동일한 규칙이 적용됩니다.
(항 연산자나 삼항 연산자 양쪽에 ASCII 공백(space)을 사용하는 규칙에 대한 내용을 설명하는 문구)
하지만 두개의 :: 콜론에서는 띄우면 안된다. Object::toString
그리고 dot(.) 연산자에서도 띄우면 안된다. object.toString()
int result = a + b;
int conditionResult = (condition) ? trueValue : falseValue;
위의 예시에서 +와 ? 연산자 양쪽에 ASCII 공백(space)을 사용하여 코드의 구조를 명확하게 표현합니다.
"연산자와 유사한" 기호들에도 공백 사용:
List<? extends Number> numbers = new ArrayList<>();
catch (Exception | AnotherException e) {
// 예외 처리 코드
}
for (String item : items) {
// 반복문 코드
}
- 쉼표(,)나 콜론(:), 세미콜론(;) 뒤의 공백 사용, 캐스트의 닫는 괄호()) 뒤의 공백 사용:
int a = 5, b = 10;
methodCall(param1, param2);
for (int i = 0; i < 5; i++) {
// code
}
int intValue = (int) doubleValue; (int)에서 ) 닫는기호
- 내용과 주석을 시작하는 이중 슬래시(//) 사이. 여러 개의 공백이 허용됩니다.(코드의 내용(content)과 주석(comment)을 시작하는 이중 슬래시(//) 사이에 공백(space)을 사용하는 규칙을 설명하는 문구)
- 주석을 시작하는 이중 슬래시(//)와 주석 텍스트 사이. 여러 개의 공백이 허용됩니다.
(주석(comment)의 시작을 나타내는 이중 슬래시(//)와 주석 텍스트 사이에 공백(space)을 사용하는 규칙에 대한 내용을 설명하는 문구) - 타입과 변수 사이의 공백 사용 ex) String name
- 배열 선언문 괄호 안에 공백 :new int[] {5, 6} 또는 new int[] { 5, 6 } (둘중 아무거나 가능선택 사항
- 타입 애너테이션 (@NonNull)과 ... 또는 [] 사이의 공백을 두어야합니다
타입애너테이션은 변수,리턴 타입등의 타입정보에 추가적인 메타데이터를 제공하는것을 말합니다.
이 규칙은 라인의 시작이나 끝에서 추가 공간을 요구하거나 금지하는 것은 아니다. 그것은 내부 공간만을 다룬다.
4.6.3 수평 정렬 : 필요하지 않음
수평 정렬은 특정 토큰이 이전 줄의 다른 특정 토큰 바로 아래에 표시되도록 코드에 다양한 수의 추가 공백을 추가하는 방법입니다.
이 관행은 허용되지만 Google 스타일에서 요구 하는 것은 아닙니다 .
이미 사용 된 장소에서 수평 정렬 을 유지할 필요조차 없습니다 .
다음은 정렬없이 정렬을 사용하는 예입니다.
private int x; // OK
private Color color; // OK
private int x; // OK, but future edits
private Color color; // 맞춰지지 않은 상태로 둘 수 있음
팁: 맞춤은 가독성을 높여준다. 하지만 미래 유지보수에서 문제를 일으킨다. 나중에 한 줄만 수정한다고 가정해보자. 이 변경으로 인해 이전에 맞춰놓은 서식이 엉망으로 남을 수 있지만 허용은 된다. 제작자에게 수정하는 것을 촉구하며, 일련의 재 포매팅을 유발할 수 있다. 그 한줄짜리 변경은 이제 "폭발 반경"을 갖는다. 이것은 최악의 경우 혼잡하지 않은 상황이 될 수 있지만 근본적으로 버전 히스토리 정보가 손상되고 검토자를 느리게하고 머지 충돌이 일어난다.
4.7 그룹화 괄호 : 권장
코드에서 선택적으로 사용되는 괄호에 관한 내용을 나타내는 문구입니다. 이 문구는 작성자와 검토자가 동의하여 코드를 보다 명확하게 이해할 수 있거나 코드의 가독성을 높일 수 있는 상황에서만 선택적인 괄호를 생략한다는 규칙을 나타냅니다. 모든 리더가 Java의 연산자 우선순위 표를 외우고 있다고 가정하는 것은 합리적이지 않습니다.
int result = a + b * c;
위의 코드에서 * 연산자는 + 연산자보다 우선순위가 높습니다.
그러나 작성자와 검토자가 동의하여 괄호 없이 작성해도 코드가 명확하게 이해될 수 있고,
가독성이 떨어지지 않을 경우에는 괄호를 생략할 수 있습니다.
int result = a + (b * c); 이것을 더 권장한다는 뜻
4.8 특정 구조
4.8.1 Enum 클래스
enum 상수의 각 컴마 다음에 개행은 선택적이다. 추가의 개행(주로 한개)도 허용된다.
메소드와 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 필요할때 선언
로컬(지역) 변수는 보통 그들이 포함된 블록이나 블록과 유사한 구조의 시작 부분에서 선언되지 않습니다. 대신, 로컬 변수는 처음 사용되는 지점 근처에서 선언됩니다(합리적인 범위 내에서), 이로써 그들의 범위를 최소화합니다. 로컬 변수 선언은 일반적으로 초기화자(initializer)를 가지고 있거나 선언 바로 다음에 즉시 초기화됩니다.
4.8.3 배열
4.8.3.1 배열 초기화 마치 블록 구조처럼
배열 초기화는 "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 라벨 (either case FOO: or default:)과 하나 이상의 명령문 (또는 마지막 명령문 그룹의 경우 0 개 이상의 명령문)으로 구성됩니다.
4.8.4.1 들여쓰기
다른 블록과 마찬가지로 스위치 블록의 내용은 +2로 들여 쓰기됩니다.
스위치 레이블 뒤에는 줄 바꿈이 있고 들여 쓰기 수준은 마치 블록이 열려있는 것처럼 +2가 증가합니다. 다음 스위치 레이블은 마치 블록이 닫힌 것처럼 이전 들여 쓰기 수준으로 돌아갑니다.
4.8.4.2 Fall-through : 주석
switch 블록 내의 각 문장 그룹은 break, continue, return, 또는 예외를 던지는 방식으로 갑작스러운 종료를 할 수 있습니다. 이렇게 하면 해당 문장 그룹이 실행되고 나서 switch 블록을 빠져나옵니다.
만약 다음 case를 계속해서 실행하는것을 원한다면 이에 대한 명시적인 주석을 달아주어야 합니다. 이 주석은 "fall-through"가 일어날 수 있음을 나타내는 역할을 합니다. 마지막 case는 주석을 달아 주지 않더라도 더이상 진행될게 없으므로 주석을 달아주지 않아도 됩니다.
4.8.4.3 default의 존재 유무
각각의 switch 문은 기본(default) 문장 그룹을 포함하고 있어야 합니다. 이러한 기본 문장 그룹은 실제로 코드가 없더라도 반드시 존재해야 합니다. 예외적으로, 열거(enum) 타입에 대한 switch 문은 해당 타입의 모든 가능한 값을 명시적으로 다루는 경우를 포함하는 경우에는 기본 문장 그룹을 생략할 수 있습니다. 이렇게 하면 특정 타입의 모든 값들을 명시적으로 처리하도록 코드를 작성할 수 있으며, 이로써 특정 값들을 놓치지 않도록 IDE나 정적 분석 도구가 경고를 발생시킬 수 있습니다.
4.8.5 애노테이션
4.8.5.1 Type-use annotations
타입 사용 어노테이션은 어노테이션이 지정된 타입의 바로 앞에 위치합니다. 즉, 해당 타입을 지정하는 부분 이전에 나타납니다. 이렇게 함으로써 어노테이션의 의미와 타입의 관계가 명확해지고, 어노테이션이 어떤 타입을 가리키는지 분명해집니다.
타입 사용 주석은 변수나 매개변수, 반환값 등의 타입을 지정하는 곳에 사용되는 주석을 말합니다. 이러한 주석은 코드에서 해당 타입이 사용되는 방식에 대한 추가 정보를 제공하거나 검사를 수행하기 위해 사용됩니다. 예를 들어, 널 포인터 예외를 방지하기 위해 어떤 변수는 절대로 널이 될 수 없음을 나타내는 주석 등이 있습니다.
@NonNull String name; // 타입 사용 주석, @NonNull 어노테이션이 타입 사용 위치에 사용됨
4.8.5.2 Class annotations
클래스에 적용되는 주석은 해당 클래스의 선언 바로 위에 위치합니다. 이러한 주석들은 클래스의 정보를 제공하거나 추가적인 설정을 나타내기 위해 사용됩니다. 클래스에 여러 주석이 적용되는 경우, 각 주석은 개별적인 라인에 나열됩니다. 즉, 한 줄에 하나의 주석이 위치하게 됩니다. 이렇게 하면 주석들이 분리되어 가독성을 높일 수 있습니다.
line-wrapping
"Line-wrapping"은 코드나 텍스트의 줄 바꿈을 의미하는 개념입니다. 코드나 텍스트가 너무 길어서 한 줄에 다 쓸 수 없을 때, 줄 바꿈을 하여 여러 줄로 나누는 작업을 말합니다.
4.8.5.3 메서드와 생성자 어노테이션
4.8.5.2와 규칙이 같으며 예외 매개변수가 없는것은 아래와 같이 선언 할 수 있다.
@Override public int hashCode() { ... }
4.8.5.4 필드 어노테이션
필드에 적용되는 애노테이션들은 한 줄에 쓸 수 있다. 예를들어,
@Partial @Mock DataLoader loader;
여기서 (possibly parameterized) 라는 말이 나오는데 어노테이션에 파라미터(매개변수)를 전달하여 어노테이션의 동작이나 의미를 조정할 수 있다는 것을 의미합니다.
@CustomAnnotation(value = "exampleValue", enabled = true)
4.8.5.5 파라미터와 지역변수 어노테이션
파라미터나 지역변수 애노테이션의 특정한 포맷팅 규칙은 없다. (annotation유형이 Type annotiation인경우 제외)
4.8.6 주석
이 섹션에서는 구현 주석을 다룹니다 . Javadoc은 섹션 7, Javadoc 에서 별도로 다루고 있습니다.
주석은 줄 바꿈 문자가 나오기 전까지만 해당 줄에 있으면 되는 것입니다. 이렇게 주석이 줄 바꿈 이전에 위치하면 그 줄은 비어있지 않은 줄로 취급됩니다.
public class CommentExample {
public static void main(String[] args) {
// 이 줄은 주석이지만, 줄 끝에 줄 바꿈 문자가 오기 전에 주석이 있으므로 줄 바꿈 전에 주석이 있는 것으로 취급됩니다.
System.out.println("Hello,");
System.out.println("World!"); // 줄 바꿈 이전에 주석이 없으므로 해당 줄은 비어있지 않은 줄입니다.
System.out.println("Java is fun."); // 이 줄은 주석이 없는 일반적인 줄입니다.
}
}
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.8 숫자 리터럴
long값을 갖는 정수 리터럴 L은 소문자가 아닌 대문자 접미사를 사용합니다 (digit(1)와의 혼동을 피하기 위해 ).
예를 들어, ⭕️ 3000000000L ❌ 3000000000l.
5. Naming
5.1 모든 식별자에 공통적인 규칙
식별자는 ASCII 숫자와 문자만을 씁니다. 어떤 일부 경우 언더 스코어( _ )를 쓰기도하며 유효한 식별자 이름은 정규식 \w+와 매칭됩니다.
( \w는 정규식에서 "단어 문자"를 의미합니다. 단어 문자는 영문 대소문자, 숫자, 밑줄(_)을 포함합니다. 즉, \w는 알파벳 문자(대소문자), 숫자, 밑줄을 허용하는 패턴을 매칭합니다. 다른 특수 문자는 포함하지 않습니다. )
구글 스타일에서는 특별한 접미사나 접두사는 쓰이지 않습니다. 예를들어 name_, mName, s_name, kName은 구글 스타일이 아닙닌다.
5.2 식별자 유형별 규칙
5.2.1 패키지 이름
패키지 이름은 모두 소문자이며 연속 된 단어는 단순히 함께 연결됩니다 (밑줄 없음).
예를 들어, ⭕️ com.example.deepspacenot ❌ com.example.deepSpace또는 com.example.deep_space.
5.2.2 클래스 이름
클래스 이름은 UpperCamelCase로 작성 됩니다.
클래스 이름은 명사나 명사구 이며 예를들어 Character 또는 ImmutableList처럼 작성됩니다.
인터페이스 이름은 명사나 명사구가 될 수 있으며 가끔은 형용사나 형용사구가 대신 쓰이기도 합니다.(예를들어 : Runnable)
어노테이션 이름 지정에 대한 특정 규칙은 없습니다.
테스트 클래스들은 테스트하려는 클래스의 이름이 앞에오고 끝에 Test를 붙여줍니다.
예를들어 HashTest 혹은 HashIntegrationTest
5.2.3 메서드 이름
메서드 이름은 lowerCamelCase로 작성 됩니다.
메서드이름은 일반적으로 동사 또는 동사구 입니다 예를들어 sendMessage 또는 stop
Junit 테스트 메서드 이름은 언더스코어( _ ) 를 이용할 수 있습니다. 이유는 논리적 구성요소를 분리시키기 위해서이며 각각을 lowerCamelCase로 나눌 수 있습니다. (예: ) transferMoney_deductsFromSource. 이것은 하나의 방법이라 설명해주는거일뿐 테스트 메서드의 이름을 지정하는 올바른 방법은 없습니다.
5.2.4 상수 이름
상수는 CONSTANT_CASE를 사용한다: 모두 대문자이고 각 단어는 하나의 언더스코어로 구분하는 형식입니다.
그런데 상수란 정확히 무엇인가요?
상수(Constants)는 그 내용이 완전히 불변하며, 메서드가 감지 가능한 부작용(side effect)이 없는 정적인(static) final 필드들을 말합니다
이는 기본 타입(primitives), 문자열(strings), 불변한 값 클래스들, 그리고 null로 설정된 것들을 포함합니다.
인스턴스의 경우 관측 가능한 상태가 바뀔수 있다면 상수가 아닙니다. 그러므로 단지 그대상을 절대 변형시키지 않으려는 의도만으로는 충분하지 않습니다.
객체를 절대로 변경하지 않을 것을 의도하는 것만으로는 부족하며, 해당 의도를 구체적인 코드로 구현하여 실제로 불변성을 유지해야 합니다. (변경을 방지하려면 필드를 final로 선언하여 불변성을 보장해야 합니다.)
예시
// Constants
static final int NUMBER = 5;
static final ImmutableList<String> NAMES = ImmutableList.of("Ed", "Ann");
static final Map<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 = {};
// 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로 작성됩니다.
이러한 이름들은 전형적으로 명사나 명사입니다. 예를들어, computedValues, index.
5.2.6 매개변수 이름
매개변수 이름은 lowerCamelCase로 작성됩니다.
public 메서드에서는 한문자로 된 매개변수 이름을 작성하지 말아야합니다.
5.2.7 지역변수 이름
지역변수 이름은 lowerCamelCase로 작성됩니다.
final로 선언되있어 불변인 경우에도 지역 변수는 상수로 간주되지 않으며 상수 스타일을 지정해서는 안됩니다.
5.2.8 타입 변수 이름
각 타입 변수의 이름은 두가지 스타일 중 하나로 지정됩니다.
- 타입 변수는 단일한 대문자 알파벳으로 이름을 짓는 것이 가능하며, 선택적으로 대문자 알파벳 뒤에 단일한 숫자를 붙일 수도 있습니다. 예를 들어, E, T, X, T2와 같은 형식의 이름이 이에 해당합니다
- 클래스 네이밍 형식을 따르는 이름에 대문자 알파벳 T를 덧붙이는 방식으로도 타입 변수 이름을 짓을 수 있습니다. 클래스의 네이밍 규칙을 따르기 때문에 의미 있는 이름을 부여할 수 있습니다. 예를 들어, RequestT, FooBarT와 같은 이름이 이에 해당합니다.
이러한 네이밍 스타일은 제네릭 타입을 정의할 때 사용되며, 해당 타입 변수가 어떤 역할을 수행하는지를 더 명확하게 표현하기 위해 사용됩니다. 타입 변수의 명명 규칙을 따르면 코드의 가독성을 향상시키고, 타입 변수가 어떤 역할을 하는지 쉽게 이해할 수 있습니다.
타입 변수(Type Variable)의 네이밍 스타일에 대한 설명을 제공합니다. 타입 변수는 제네릭 프로그래밍에서 사용되며, 클래스나 메서드 안에서 일반적인 타입 대신에 사용될 타입을 나타내는 변수입니다.
5.3 카멜 케이스의 정의
가끔은 영어 구문을 캐멀 케이스로 변환하는 합리적인 방법이 여러 가지일 수 있습니다. 특히 약어나 "IPv6" 또는 "iOS"와 같은 예외적인 구조가 포함된 경우입니다. Google 스타일은 예측 가능성을 높이기 위해 다음과 같이 (거의) 결정적인 방법을 명시하고 있습니다.
약어 : ASAP = as soon as possible와 같이 줄인것
- 구를 일반 ASCII로 변환하고 어퍼스토로피를 제거하십시오. 예를 들어 "Müller's algorithm"은 "Muellers algorithm"이 될 수 있습니다.
- 이 결과를 공백이나 하이픈으로 단어를 나눕니다.
- 권장: 단어가 이미 일반적으로 사용되는 카멜케이스의 모양을 갖고 있는 경우 이를 구성하는 부분들로 분할합니다. 예를들어 "AdWords"를 "ad words"로 변환합니다. 그러나 "iOS"와 같은 단어는 캐멀 케이스 형식을 따르지 않습니다. 이 단어는 어떤 규약에도 부합하지 않는 형태를 가지고 있어서 규칙에 따라 구성 요소로 분해할 필요가 없습니다. 따라서 "iOS"는 해당 권장 사항의 대상이 되지 않습니다.
- 이제 모든 항목을 소문자로 만들고 다음 항목의 첫번째 문자만 대문자로 지정합니다.
- 각단어는 첫번째는 upeercase로 표시
- 각 단어지만 첫번째는 제외, 첫번째는 lowercase
- 마지막으로 모든 단어를 단일 식별자를 통해 결합합니다.
원래 단어의 대소문자는 거의 완전히 무시됩니다.
예시
Prose form | Correct | Incorrect |
"XML HTTP request" | XmlHttpRequest | XMLHTTPRequest |
"new customer ID" | newCustomerId | newCustomerID |
"inner stopwatch" | innerStopwatch | innerStopWatch |
"supports IPv6 on iOS?" | supportsIpv6OnIos | supportsIPv6OnIOS |
"YouTube importer" | YouTubeImporter YoutubeImporter* |
* 허용되지만 권장되지는 않습니다.
참고: 영어에서는 모호하게 하이픈이 있는 단어가 몇개 있는데 예를들어, "nonempty" 나 "non-empty"의 경우에는 둘 다 맞습니다.. 그래서 메소드 이름이 checkNonempty나 checkNonEmpty의 경우에도 둘다 맞습니다.
6. 프로그래밍 실습
6.1 @Override : 항상 사용됨
여기에는 수퍼 클래스 메소드를 재정의하는 클래스 메소드, 인터페이스 메소드를 구현하는 클래스 메소드, 수퍼 인터페이스 메소드를 재 지정하는 인터페이스 메소드가 포함됩니다.
서브클래스의 메서드가 슈퍼클래스의 메서드를 오버라이딩할 때는 @Override 어노테이션을 사용해야 합니다. 이것은 서브클래스에서 슈퍼클래스의 메서드를 재정의(override)한다는 것을 나타냅니다.
클래스가 인터페이스의 메서드를 구현할 때도 @Override 어노테이션을 사용해야 합니다. 이는 클래스가 인터페이스에서 정의된 메서드를 정확히 구현하고 있다는 것을 나타냅니다.
인터페이스가 슈퍼인터페이스의 메서드를 재지정할 때도 @Override 어노테이션을 사용해야 합니다. 이는 인터페이스가 슈퍼인터페이스에서 정의된 메서드를 재지정하고 있다는 것을 나타냅니다.
예외적인 상황으로, @Override 어노테이션은 부모 메서드가 @Deprecated 어노테이션을 가진 경우 생략할 수 있습니다.
@Deprecated 어노테이션은 메서드가 더 이상 사용되지 않거나 폐기되었음을 나타내는 역할을 합니다. 이런 경우에는 이미 폐기된 메서드를 오버라이딩하는 상황에서 불필요한 경고를 피하기 위해 @Override 어노테이션을 생략할 수 있습니다.
@Override 어노테이션은 메서드가 다른 메서드를 오버라이딩(overriding)하거나 구현(implement)할 때 사용되며, 코드의 가독성을 높이고 컴파일러가 오버라이딩을 검증할 수 있도록 도와줍니다.
6.2 예외 잡기 : 생략하지 말것
아래에 언급된 경우를 제외하고 발생한 예외에 대해 아무작업도 수행하지 않는것은 거의 올바른 일이 아닙니다.
일반적으로 로깅하거나 "불가능한" 예외라고 간주하여 AssertionError로 다시 던지는 것이 일반적인 대응 방법입니다
(Assertion Error란 조건이 거짓인 경우에 실행을 중단시키고 내는 에러를 말합니다)
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)을 가지거나 시작하는 예외가 발생한 경우에는 해당 예외를 무시하고 주석 없이 처리하는 것이 가능합니다. (catch 블록에서 아무것도 없으면 주석을 달아야했었음)
다음 예제는 테스트에서 예외가 나오는게 확실한 상황에서 사용되는 대중적인 형식으로 주석이 필요가 없습니다.
try {
emptyStack.pop();
fail();
} catch (NoSuchElementException expected) {
}
6.3 정적 멤버 : 클래스를 이용
정적 클래스 멤버에 접근할 때 해당 클래스의 이름을 사용하는것으로 한정하는것을, 그 클래스의 타입을 가리키는 참조나 표현식을 사용하는 것보다 올바른 방법이라고 알려주고 있습니다.
왜냐하면 정적 멤버가 클래스 자체와 연관되어 있기 때문에, 클래스의 인스턴스를 생성하지 않고도 바로 접근할 수 있기 때문입니다.
클래스 자체와 연관되어있다는것은 정적 멤버(정적 필드 또는 정적 메서드)가 클래스 레벨에서 정의되고 클래스가 로드되면 메모리에 상주한다는 것을 의미합니다. 이로 인해 정적 멤버는 클래스의 인스턴스 생성 여부와 관계없이 클래스 이름을 통해 바로 접근할 수 있습니다.
예시
Foo aFoo = ...;
Foo.aStaticMethod(); // good
aFoo.aStaticMethod(); // bad
somethingThatYieldsAFoo().aStaticMethod(); // very bad
6.4 Finalizers : 사용되지 않음
Object.finalize 메서드를 오버라이딩(overriding)하는 것은 극히 드물다는 것을 나타내고 있습니다. Object.finalize 메서드는 자바의 모든 클래스가 상속받는 Object 클래스에 정의된 메서드로, 객체가 가비지 컬렉션의 대상이 될 때 호출되는 메서드입니다. 이 메서드를 오버라이딩하여 사용하는 것은 매우 드물고, 실제로 권장되지 않는다는 것을 알려주고 있습니다.
7 Javadoc
7.1 포맷
7.1.1 일반 형태
기본적인 형태는 다음 예시에서 볼 수 있습니다.
기본형태
/**
* Multiple lines of Javadoc text are written here,
* wrapped normally...
*/
public int method(String p1) { ... }
한줄
/** An especially short bit of Javadoc. */
기본 형식은 항상 허용되며 Javadoc 블럭이 한 줄에 맞는다면 한줄형식으로 대체가능합니다. 이 경우에는 @return 같은 블럭 태그가 없을 경우에 적용가능합니다.
7.1.3 블록 태그
주석 내에서 표준 "블록 태그"는 다음 순서로 나타나야 합니다:
@param: 메서드나 함수의 매개변수에 대한 설명을 포함합니다.
@return: 메서드나 함수의 반환 값에 대한 설명을 포함합니다.
@throws 또는 @exception: 메서드나 함수가 던질 수 있는 예외에 대한 설명을 포함합니다
@deprecated: 사용이 권장되지 않는 경우에 대한 설명을 포함합니다.
위의 네 가지 블록 태그는 빈 설명 없이 사용되어서는 안 됩니다.각 태그는 해당하는 내용을 설명하는 설명문이 포함되어야 합니다.
블록 태그가 한 줄에 맞지 않을 경우, 이어지는 줄은 @ 기호에서 네 개 이상의 공백을 들여쓰기하여 작성합니다.
7.2 요약 문구
Javadoc은 간단한 요약 문구로 시작됩니다. 이 문구는 매우 중요하며 이는 클래스 및 메서드 인덱스와 같은 특정 위치에 나타나는 내용입니다.
"메서드 인덱스"는 프로그래밍 문서나 개발 환경에서 사용되는 용어 중 하나입니다. 일반적으로 프로그래밍 언어나 라이브러리의 메서드(method)들을 정리하고 검색하기 쉽도록 제공되는 목록이나 색인을 말합니다.
"요약 문구"는 명사구나 동사구와 같은 구문의 조각입니다. 완전한 문장이 아니며, "A {@code 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 멤버 마다 나타나야합니다.
단 몇 개의 예외는 다음과 같습니다. (여기서 예외란 이외의 추가적인 상황에서 Javadoc을 쓸 수 있다는것을 말하는거 같습니다.)
Section 7.3.4, Non-required Javadoc에 설명 된대로 추가 Javadoc 컨텐츠가있을 수도 있습니다 .
7.3.1 예외적인 상황 : 자체적으로 설명되는 멤버
"getFoo()"와 같이 "간단하고 명백한" 멤버에 대해서는 Javadoc 작성이 선택 사항입니다. 이 경우에는 "Returns the foo."와 같이 그 멤버의 목적을 간단히 설명하는 내용만으로 충분할 경우, Javadoc을 작성하지 않아도 됩니다.
단 이 예외를 이용하여 일반적인 독자가 알아야 할 중요한 정보를 생략하는 것은 적절하지 않습니다. 예를 들어, "getCanonicalName"이라는 메서드의 경우, 단순히 "/** Returns the canonical name. */"라고 작성하며 문서를 생략하는 것은 적절하지 않습니다. 왜냐하면 일반 독자가 "canonical name"이라는 용어의 의미를 모를 수 있기 때문입니다.
7.3.2 예외 적인 상황 :overrrides
Javadoc은 수퍼 타입 메소드를 오버라이드 하는 메소드에 항상 존재하는 것은 아닙니다.
7.3.4 필수가 아닌 Javadoc
다른 클래스와 멤버들은 원하는 또는 필요한 Javadoc을 가지고 있습니다.
어떤 클래스나 멤버의 전반적인 목적이나 동작을 정의하는 데 구현 주석이 사용될 경우, 그 주석은 Javadoc 형식으로 작성됩니다 (/**를 사용하여). 이것은 클래스나 멤버의 기능을 문서화하고 설명하기 위한 것입니다.
필수가 아닌 Javadoc은 섹션 7.1.2, 7.1.3 및 7.2의 형식화 규칙을 따르도록 엄격하게 요구되지는 않지만 물론 권장됩니다.
수 사항이 아닌 Javadoc은 필요한 내용을 포함하면서도 추가적인 형식적인 규칙을 따를 필요는 없으나, 문서화의 일관성과 가독성을 위해 가능한한 형식 규칙을 따르는 것이 좋습니다.