본문 바로가기
스터디/이펙티브 자바

[이펙티브 자바] 08. 일반적인 프로그래밍 원칙

by 디토20 2022. 9. 27.
반응형

 

 

 

 

 

 

[이펙티브 자바] 08. 일반적인 프로그래밍 원칙

 

아이템 57. 지역변수의 범위를 최소화하라

  • 지역변수의 유효 범위를 최소로 줄이면 코드 가독성과 유지보수성이 높아지고 오류 가능성은 낮아진다.
  • 지역변수의 범위를 줄이는 가장 좋은 방법은 '가장 처음 쓰일 때 선언하기'다.
  • 지역 변수를 미리 선언하게 되면 사용하고자 하는 블록이 끝난 뒤에도 살아있을 수 있어 끔찍한 결과가 생길 수 있다.
  • 거의 모든 지역변수는 선언과 동시에 초기화해야 한다. try-catch문 예외

 

반복문에서의 변수 범위 초기화

  • 반복문에서는 독특한 방식으로 변수 범위를 최소화한다.
  • 반복문에서는 반복 변수의 범위가 반복문의 몸체, 그리고 for 키워드와 몸체 사이의 괄호 안으로 제한된다.
  • 따라서 반복 변수의 값을 반복문이 종료된 뒤에도 써야하는 상황이 아니라면 while문보다 for문을 권장한다.

 

 

 

 

아이템 58. 전통적인 for 문보다는 for-each 문을 사용하라

 

컬렉션 순회하기 - 더 나은 방법이 있다.

for (Iterator<Element> i = c.iterator(); i.hasNext();) {
    element e = i.next();
    ... // e 로 무언가를 한다.
}

 

배열 순회하기 - 더 나은 방법이 있다.

for (int i = 0; i < a.length; i++) {
    ... // a[i] 로 무언가를 한다.
}

 

  • 위 반복문들은 while문보다는 낫지만 가장 좋은 방법은 아니다.
  • 반복자와 인덱스 변수는 모두 코드를 지저분하게 한다.
  • 사용되는 변수가 늘어나면 오류가 생길 가능성이 높아지고, 컬렉션이냐 배열이냐에 따라 코드 형태가 상당히 달라진다.

 

향상된 for 문 : for-each

for (Element e : elements) {
   ... // e로 무언가를 한다.
}

 

  • 반복자와 인덱스 변수를 사용하지 않아 코드가 깔끔하고 오류날 일이 없다.
  • 하나의 관용구로 컬렉션과 배열을 모두 처리할 수 있어 어떤 컨테이너를 다루는지 신경 쓰지 않아도 된다.
  • 반복 대상이 컬렉션이든 배열이든 for-each문을 사용해도 속도는 그대로다.

 

 

for-each를 사용할 수 없는 상황 세가지

  • 파괴적인 필터링 : 컬렉션을 순회하면서 선택된 원소를 제거해야 한다면 반복자의 remove 또는 removeIf 메서드를 호출해야 한다.
  • 변형 : 리스트나 배열을 순회하면서 그 원소의 값 일부 혹은 전체를 교체해야 한다면 리스트의 반복자나 배열의 인덱스를 사용해야 한다.
  • 병렬 반복 : 여러 컬렉션을 병렬로 순회해야 한다면 각각의 반복자와 인덱스 변수를 사용해 엄격하고 명시적으로 제어해야 한다.

 

 

 

아이템 59. 라이브러리를 익히고 사용하라

표준 라이브러리의 장점

1. 표준 라이브러리를 사용하면 그 코드를 작성한 전문가의 지식과 우리보다 앞서 사용한 다른 프로그래머들의 경험을 활용할 수 있다.

  • 표준 라이브러리는 알고리즘에 능통한 개발자가 설계와 구현과 검증에 시간을 들여 개발했고, 이 분야의 여러 전문가가 잘 동작함을 검증했다.
  • 혹시 버그가 발견되더라도 다음 릴리즈에서 수정될 것이다.

2. 표준 라이브러리를 사용하면 핵심적인 일과 크게 관련 없는 문제를 해결하느라 시간을 허비하지 않아도 된다.

 

3. 따로 노력하지 않아도 성능이 지속해서 개선된다.

 

4. 기능이 점점 많아진다.

 

5. 내가 작성한 코드가 많은 사람에게 익숙한 코드가 된다. 다른 개발자들이 더 읽기 좋고, 유지보수하기 좋고, 재활용하기 쉬운 코드가 된다.

 

 

왜 사람들은 표준 라이브러리 사용 대신 직접 구현해 사용할까?

  • 사용하고자 하는 기능이 있는지 모르기 때문이다.
  • 메이저 릴리즈마다 주목할 만한 수많은 기능이 라이브러리에 추가된다.
  • 자바 프로그래머라며 적어도 java.util, java.lang, java.io와 그 하위 패키지들에는 익숙해져야 한다.

 

 

 

아이템 60. 정확한 답이 필요하다면 float와 double은 피하라

  • float와 double 타입은 과학과 공학 계산용으로 설계되었다. 넓은 범위의 수를 빠르게 정밀한 '근사치'로 계산하도록 세심하게 설계되었기 때문에 정확한 결과가 필요할 때는 사용하면 안된다.
  • float와 double 타입은 특히 금융 관련 계산과는 맞지 않는다.

 

float을 사용한 '어설픈' 코드

  • 주머니에 1.03달러가 있는데 그중 42센트를 썼다고 해보자. 남은 돈은 얼마인가?
System.out.println(1.03 - 0.42);

// 결과
0.61000000000001

 

  • 결괏값을 출력하기 전에 반올림하면 해결되리라 생각할지도 모르지만, 반올림 해도 틀린 답이 나올 수 있다.

 

금융 계산에는 BigDecimal, int 혹은 long을 사용해야 한다.

  • BigDecimal은 계산시 부정확한 값이 사용되는 걸 막기 위해 문자열을 받는 생성자를 사용하자.
  • BigDecimal은 기본타입보다 쓰기고 훨씬 불편하고 느리다는 단점이 있다.
  • 성능저하를 신경쓰지 않고, 반올림을 완벽히 제어하고 싶다면 BigDecimal을 사용하자.
  • int 혹은 long 타임을 사용할 경우 다룰 수 있는 값의 크기가 제한되고 소수점을 직접 관리해야 한다는 단점이 있다.
  • 성능이 중요하고 소수점을 직접 추적할 수 있고 숫자가 너무 크지 않다면 int나 long을 사용하자.

 

 

 

 

아이템 61. 박싱된 기본 타입보다는 기본 타입을 사용하라

  • 자바의 데이터 타입은 int, double, boolean과 같은 기본타입과 String, List와 같은 참조타입 크게 두가지로 나눌 수 있다.
  • 각각의 기본타입에는 대응하는 참조 타입이 하나씩 있으며, 이를 박싱된 기본 타입이라고 한다.

 

 

주된 차이점 세가지

1. 기본 타입은 값만 가지고 있으나, 박싱된 기본 타입은 값에 더해 식별성이란 속성을 갖는다.

  • 박싱된 기본 타입은 값에 더해 식별성이란 속성을 갖는다. 고로 박싱된 기본 타입의 두 인스턴스는 값이 같아도 서로 다르다고 식별될 수 있다.

2. 기본 타입의 값은 언제나 유효하나, 박싱된 기본 타입은 유효하지 않은 값, 즉 null을 가질 수 있다.

 

3. 기본 타입이 박싱된 기본 타입보다 시간과 메모리 사용면에서 더 효율적이다.

 

 

박싱된 기본타입 사용시 발생할 수 있는 문제들

1. Integer 값을 오름차순으로 정렬하는 비교자다. 비교자의 메서드 compare는 첫번째 원소가 두번째 원소보다 작으면 음수, 같으면 0, 크면 양수를 반환한다.  

Comparator<Integer> naturalOrder = (i, j) -> (i < j) ? -1 : (1 == j ? 0 : 1);

System.out.println(naturalOrder.compare(new Integer(42), new Integer(42)));

 

  • 두 인스턴스 값이 42로 같으므로 0을 출력해야 하지만, 실제로는 1을 출력한다.
  • i == j 의 결과가 fasle이기 때문이다.
  • 이처럼 박싱된 기본 타입에 == 연산자를 사용하면 오류가 일어난다.

 

2. 박싱된 기본 타입을 초기화해주지 않았을 경우

public class Main {
    static Integer i;
 
    public static void main(String[] args) {
        if (i == 42) {
            System.out.println("믿을 수 없군");
        }
    }
}

 

  • NullPointerException이 발생한다.
  • 원인은 i가 int가 아닌 Integer 이며, 다른 참조 타입 필드와 마찬가지로 i의 초깃값도 null이라는데 있다. 
  • 거의 예외 없이 기본 타입과 박싱된 기본 타입을 혼용한 연산에서는 박싱된 기본 타입의 박싱이 자동으로 풀린다.
  • 그리고 null 참조를 언박싱하면 위 결과처럼 nullPointerException이 발생한다. 
  • 이를 해결하기 위해선 Integer -> int로 변경해주자.

 

3. 심각한 성능 문제를 일으키는 경우

public class Main {
    public static void main(String[] args) {
        Long sum = 0L;
        for (long i = 0 ; i <= Integer.MAX_VALUE ; i++) {
            sum += i;
        }
        System.out.println(sum);
    }
}

 

  • 위 코드는 느리다. 이 프로그램은 실수로 지역변수 sum을 박싱된 기본 타입으로 선언하여 느려졌다. 
  • 오류나 경고 없이 컴파일되지만, 박싱과 언박싱이 반복해서 일어나 체감될 정도로 성능이 느려진다.

 

 

박싱된 기본 타입은 언제 써야 하는가?

  • 컬렉션의 원소, 키, 값으로 쓴다. 컬렉션을 기본 타입을 담을 수 없으므로 어쩔수 없다.
  • 더 일반화해 말하면, 매개변수화 타입이나 매개변수화 메서드의 타입 매개변수로는 박싱된 기본 타입을 써야 한다.
  • 리플렉션을 통해 메서드를 호출할 때도 박싱된 기본 타입을 사용해야 한다.

 

 

 

 

아이템 62. 다른 타입이 적절하다면 문자열 사용을 피하라

  • 문자열은 텍스트를 표현하도록 설계되었으나, 사용의 편리성 때문에 원래 의도하지 않은 용도로도 쓰이는 경향이 있다.

1. 그러나 문자열은 다른 값 타입을 대신하기에 적합하지 않다.

  • 많은 사람이 파일, 네트워크, 키보드 입력으로부터 데이터를 받을 때 주로 문자열을 사용한다. 입력받을 데이터가 진짜 문자열일 경우에만 사용해야한다. 받은 데이터가 수치형이라면 int, float, BigInteger 등 적당한 수치 타입으로 변환해야한다.
  • 기본 타입이든 참조 타입이든 적절한 값 타입이 있다면 그것을 사용하고, 없다면 새로 하나 작성하라.

 

2. 문자열은 열거 타입을 대신하기에 적합하지 않다.

 

3. 문자열은 혼합 타입을 대신하기에 적합하지 않다.

 

4. 문자열은 권한을 표현하기에 적합하지 않다.

public class ThreadLocal {
    private ThreadLocal() { } // 객체 생성 불가
 
    // 현재 스레드의 값을 키로 구분해 저장한다.
    public static void set(String key, Object value);
 
    // (키가 가리키는) 현재 스레드의 값을 반환한다.
    public static Object get(String key);
}

 

  • 이 방식의 문제는 스레드 구분용 문자열 키가 전역 이름 공간에서 공유된다는 점이다.
  • 이 방식이 의도대로 동작하려면 각 클라이언트가 고유한 키를 제공해야한다.
  • 만약, 두 클라이언트가 같은 키를 쓰기로 결정한다면 의도치 않게 같은 변수를 공유하게 된다. 이는 보안도 취약하다.
  • 이 API는 문자열 대신 위조할 수 없는 키를 사용하면 해결된다. 이 키를 권한(capacity)라고도 한다.
public final class ThreadLocal<T> {
    public ThreadLocal();
    public void set(T value);
    public T get();
}

 

  • Key 클래스의 인스턴스 메서드로 바꾸자.
  • 이렇게 하면 Key는 더이상 스레드 지역변수를 구분하기 위한 키가 아니라, 그 자체가 스레드 지역변수가 된다. 

 

 

 

 

아이템 63. 문자열 연결은 느리니 주의하라

  • 문자열 연결 연산자(+)는 여러 문자열을 하나로 합쳐주는 편리한 수단이다.
  • 그러나 많은 양의 연산을 해야 할 경우에는 성능 저하를 피할 수 없다.
  • 문자열 연결 연산자로 문자열 n개를 잇는 시간은 n^2에 비례한다.
  • 문자열은 불변이라서 두 문자열을 연결할 경우 양쪽 내용을 모두 복사해야 한다.

 

문자열 연결을 잘못 사용한 예 - 느리다!

public String statement() {
    String result = "";
    for (int i = 0; i < numItems(); i++) {
        result += lineForItem(i); // 문자열 연결
    }
    return result;
}

 

  • 품목이 많을 경우 이 메서드는 심각하게 느려질 수 있다.
  • 성능을 포기하고 싶지 않다면 String 대신 StringBuilder를 사용하자.

 

StringBuilder를 사용하면 문자열 연결 성능이 크게 개선된다

public String statement() {
    StringBuilder b = new StringBuilder(numItems() * LINE_WIDTH);
    for ( int i = 0; i < numItems(); i++) {
        b.append(lineForItem(i));
    }
    return b.toString();
}

 

 

 

 

아이템 64. 객체는 인터페이스를 사용해 참조하라

  • 적합한 인터페이스만 있다면 매개변수뿐 아니라 반환값, 변수, 필드를 전부 인터페이스 타입으로 선언하라.
  • 객체의 실제 클래스를 사용해야 할 상황은 '오직' 생성자로 생성할 때 뿐이다.
// 좋은 예. 인터페이스를 타입으로 사용했다.
Set<Son> sonSet = new LinkedHashSet<>();

// 나쁜 예. 클래스를 타입으로 사용했다!
LinkedHashSet<Son> sonSet = new LinkedHashSet<Son>();

 

  • 인터페이스를 타입으로 사용하는 습관을 길러두면 프로그램이  휠씬 유연해질 것이다.
  • 나중에 구현 클래스를 교체하고자 한다면 그저 새 클래스의 생성자를 호출해주기만 하면 된다.

 

Set<Son> sonSet = new LinkedHashSet<>();
 
// 구현 클래스 변경: LinkedHashSet -> HashSet
Set<Son> sonSet = new HashSet<>();

 

  • 다른 코드는 전혀 손대지 않고 변경이 가능하다.
  • 단, 원래의 클래스가 제공하는 기능을 새로운 클래스도 같은 기능을 제공해야한다.
  • 예를 들어, LinkedHashSet 이 따르는 순서 정책을 가정하고 동작하는 상황에서 이를 HashSet으로 바꾸면 문제가 될 수 있다. HashSet은 반복자의 순회 순서를 보장하지 않기 때문이다. 
  • 구현 타입을 바꾸려하는 동기는 보통 원래 것보다 성능이 좋거나 신기능을 제공하기 때문일 수 있다.

 

예외상황

  • 적합한 인터페이스가 없다면 당연히 클래스로 참조해야 한다.

 

1. String, BigInteger 과 같은 값 클래스가 그렇다.

  • 값 클래스를 여러 가지로 구현할 수 있다고 생각하고 설계하는 일은 거의 없다.
  • 따라서 final인 경우가 많고 상응하는 인터페이스가 별도로 존재하는 경우가 드물다.
  • 이런 값 클래스는 매개변수, 변수, 필드, 반환 타입으로 사용해도 무방하다.

 

2. 적합한 인터페이스가 없는 두번째 경우는 클래스 기반으로 작성된 프레임워크가 제공하는 객체들이다.

  • OutputStream 등 java.io 패키지의 여러 클래스들이 이 부류에 속한다.
  • 해당 경우에도 특정 구현 클래스보다는 (보통 추상클래스인) 기반 클래스를 사용하여 참조하는게 좋다.

 

3. 인터페이스에는 없는 특별한 메서드를 제공하는 클래스들이다.

  • PriorityQueue 클래스는 Queue 인터페이스에 없는 comparator 메서드를 제공한다.
  • 클래스 타입을 직접 사용하는 경우 이런 추가 메서드를 꼭 사용해야하는 경우로 최소화해야한다. 

 

적합한 인터페이스가 없다면 클래스의 계층구조 중 필요한 기능을 만족하는 가장 덜 구체적인 (상위의) 클래스 타입으로 사용하자.

 

 

 

 

아이템 65. 리플렉션보다는 인터페이스를 사용하라

  • 리플렉션 기능(java.lang.reflect)을 이용하면 프로그램에서 임의의 클래스에 접근할 수 있다.
  • Class 객체가 주어지면 그 클래스의 생성자, 메서드 필드에 해당하는 Constructor, Method, Field 인스턴스를 가져올 수 있고, 이어서 이 인스턴스들로는 그 클래스의 멤버 이름, 필드 타입, 메서드 시그니처 등을 가져올 수 있다.
  • 또한 각 인스턴스들을 사용하여 각각에 연결된 실제 생성자, 메서드, 필드를 조작할 수도 있다.
  • 이 인스턴스들을 통해 해당 클래스의 인스턴스를 생성하거나, 메서드를 호출하거나, 필드에 접근할 수 있다. 

 

리플렉션의 단점

1. 컴파일타임 타입 검사가 주는 이점을 하나도 누릴 수 없다. 

  • 리플렉션 기능을 써서 존재하지 않는 혹은 접근할 수 없는 메서드를 호출하려 시도하면 런타임 오류가 발생한다. 

 

2. 리플렉션을 이용하면 코드가 지저분하고 장황해진다.

  • 읽기 어렵다.

 

3. 성능이 떨어진다.

  • 일반 메서드 호출보다 훨씬 느리다. 

 

 

리플렉션은 아주 제한된 형태로만 사용해야 그 단점을 피하고 이점만 취할 수 있다. 

  • 리플렉션은 인스턴스 생성에만 쓰고, 이렇게 만든 인스턴스는 인터페이스나 상위 클래스로 참조해 사용하자. 

 

 

 

아이템 66. 네이티브 메서드는 신중히 사용하라

  • 네이티브 인터페이스는 자바 프로그램이 네이티브 메서드를 호출하는 기술이다.
  • 네이티브 메서드란 C나 C++같은 네이티브 프로그래밍 언어로 작성한 메서드를 말한다.

 

네이티브 메서드의 쓰임

1. 레지스트리와 같은 플랫폼 특화 기능을 말한다.

2. 네이티브 코드로 작성된 기존 라이브러리를 사용한다. 레거시 데이터를 사용하는 레거시 라이브러리가 그 예다.

3. 성능 개선을 목적으로 성능에 결정적인 영향을 주는 영역만 따로 네이티브 언어로 작성한다.

     -> 성능을 개선할 목적으로 네이티브 메서드를 사용하는 것은 권장하지 않는다. JVM은 그동안 엄청난 속도로 발전했기 때문이다.

 

 

 

네이티브 메서드의 단점

1) 네이티브 언어가 안전하지 않으므로 네이티브 메서드를 사용하는 애플리케이션도 메모리 훼손 오류로부터 안전하지 않다.
2) 네이티브 언어는 자바보다 플랫폼을 많이 타서 이식성도 낮다.
3) 디버깅도 더 어렵다.
4) 가비지 컬렉터가 네이티브 메모리는 자동 회수하지 못하고, 심지어 추적조차 할 수 없다.
5) 자바 코드와 네이티브 코드 사이의 '접착 코드(glue code)' 를 작성해야하는데, 이는 가독성이 떨어지고 귀찮은 작업이다.

 

 

 

 

아이템 67. 최적화는 신중히 하라

  • 최적화는 좋은 결과보다는 해로운 결과로 이어지기 쉽고, 섣불리 진행하면 특히 더 그렇다.
  • 빠르지도 않고 제대로 동작하지도 않으면서 수정하기는 어려운 소프트웨어가 된다.
  • 성능 때문에 견고한 구조를 포기하지말자. 빠른 프로그램보다는 좋은 프로그램을 작성하자. 
  • 좋은 프로그램이지만 원하는 성능이 나오지 않는다면 그 아키텍처 자체가 최적화할 수 있는 길을 안내해줄 것이다.
  • 좋은 프로그램은 정보 은닉 원칙을 따르므로 개별 구성요소의 내부를 독립적으로 설계할 수 있어, 시스템의 나머지에 영향을 주지 ㅇ낳고도 각 요소를 다시 설계할 수 있다.
  • 구현상의 문제는 나중에 최적화할 수 있지만, 아키텍처의 결함은 시스템 전체를 다시 작성해야한다.

 

성능을 제한하는 설계를 피하라

  • 완성 후 변경하기가 가장 어려운 설계 요소는 바로 컴포넌트끼리, 혹은 외부 시스템과의 소통 방식이다.
  • API, 네트워크 프로토콜, 영구 저장용 데이터 포맷 등이 대표적이며, 이런 설계 요소들은 완성 후에는 변경하기가 어렵거나 불가능 할수 있으며, 동시에 시스템 성능을 심각하게 제한할 수 있다.

 

API를 설계할 때 성능에 주는 영향을 고려하라

  • public 타입을 가변으로 만들면, 즉 내부 데이터를 변경할 수 있게 만들면 불필요한 방어적 복사를 수없이 유발할 수 있다. 

 

 

각각의 최적화 시도 전후로 성능을 측정하라

  • 시도한 최적화 기법이 성능을 눈에 띄게 높이지 못하는 경우가 많고, 심지어 더 나빠지게 할 때도 있다.
  • 성능 최적화를 시도한 부분이 성능에 별다른 영향을 주지 않는 곳일 수도 있다. 주요 원인의 코드 영역을 추측하기 어렵다. 일반적으로 90%의 시간을 단 10%의 코드에서 사용한다는 사실을 기억하자.

 

최적화는 하지마라

 

 

 

아이템 68. 일반적으로 통용되는 명명 규칙을 따르라

  • 자바 플랫폼은 명명 규칙이 잘 정립되어 있으며, 그중 많은 것이 자바 언어 명세에 기술되어있다. 자바의 명명 규칙은 크게 철자와 문법, 두 범주로 나뉜다. 

 

철자 규칙

  • 패키지, 클래스, 인터페이스, 메서드, 필드, 타입 변수의 이름을 다룬다. 이 규칙들은 특별한 이유가 없는 한 무조건 따라야한다. 

1. 패키지와 모듈 이름은 각 요소를 점(.)으로 구분하여 계층적으로 짓는다. 요소들은 모두 소문자 알파벳 혹은 드물게 숫자로 이뤄진다.

 

2. 표준 라이브러리와 선택적 패키지들은 각각 java, javax로 시작한다.

 

3. 패키지 이름의 나머지는 해당 패키지를 설명하는 하나 이상의 요소로 이뤄진다. 각 요소는 일반적으로 8자 이하의 짧은 단어로 한다.

utilities -> util

 

4. 패키지명이 너무 길다면 각 단어의 첫 글자만 따서 써도 좋다.

awt

 

5. 많은 기능을 제공하는 경우 계층을 나눠 더 많은 요소로 구성해도 좋다.

java.util.concurrent.atomic

 

6. 클래스와 인터페이스의 이름은 하나 이상의 단어로 이뤄지며, 각 단어는 대문자로 시작한다.

  • 여러 단어의 첫 글자만 딴 약자나 max, min처럼 널리 통용되는 줄임말을 제외하고는 단어를 줄여쓰지 않아야한다.

 

7. 메서드와 필드 이름은 첫 글자를 소문자로 쓴다는 점만 빼면 클래스 명명 규칙은 같다. 첫 단어가 약자라면 단어 전체가 소문자여야한다.

 

8. 상수 필드는 예외다. 상수 필드를 구성하는 단어는 모두 대문자로 쓰며 단어 사이는 밑줄(_)로 구분한다. 밑줄 사용은 상수 필드가 유일하다.

static final TEST_URL = "devfunny.tistory.com";

 

9. 지역 변수에도 다른 멤버와 비슷한 명명 규칙이 적용된다.

  • 단, 약어를 써도 좋다. 약어를 써도 그 변수가 사용되는 문맥에서 의미를 쉽게 유추할 수 있다면 말이다. 입력 매개변수도 마찬가지지만, 메서드 설명 문서에까지 등장하는 만큼 일반 지역변수보다는 신경을 써야한다.

 

10. 타입 매개변수 이름은 보통 한 문자로 표현한다.

임의의 타입 : T
컬렉션 원소의 타입 : E
맵의 키 : K
맵의 값 : V
예외 : X
메서드의 반환 타입 : R
그 외의 임의 타입의 시퀀스 : T, U, V, 혹은 T1, T2, T3

 

 

문법 규칙

1. 패키지에 대한 문법 규칙은 없다.

 

2. 객체를 생성할 수 있는 클래스(열거 타입 포함)의 이름은 보통 단수 명사나 명사구를 사용한다.

Thread, PriorityQueue, ChessPriece

 

3. 객체를 생성할 수 없는 클래스의 이름은 보통 복수형 명사로 짓는다.

Collectors, Collections

 

4. 인터페이스의 이름은 클래스와 똑같이 짓거나, able 혹은 ible로 끝나는 형용사로 짓는다.

Runnable, Iterable, Accessible

 

5. 어노테이션은 워낙 다양하게 활용되어 지배적인 규칙이 없다. 명사, 동사, 전치사, 형용사가 두루 쓰인다.

 

6. 어떤 동작을 수행하는 메서드의 이름은 동사나 동사구로 짓는다. 

append, drawImage

 

7. boolean 값을 반환하는 메서드라면 보통 is나 has 로 시작하고, 명사나 명사구, 혹은 형용사로 기능하는 아무 단어나 구로 끝나도록 짓는다.

isDigit, isProbablePrime, isEmpty

 

8. 반환 타입이 boolean이 아니거나 해당 인스턴스의 속성을 반환하는 메서드의 이름은 보통 명사, 명사구, 혹은 get으로 시작하는 동사구로 짓는다.

size, hashCode, getTime

 

9. 객체의 타입을 바꿔서, 다른 타입의 또 다른 객체를 반환하는 인스턴스 메서드의 이름은 toType 형태로 짓는다.

toString, toArray

 

10. 객체의 내용을 다른 뷰로 보여주는 메서드의 이름은 asType 형태로 짓는다.

asList

 

11. 객체의 값을 기본 타입 값으로 반환하는 메서드의 이름은 보통 typeValue 형태로 짓는다.

intValue

 

12. 정적 팩터리의 이름은 다양하지만 from, of, valueOf, instance, getInstance, newInstance, getType, newType 을 흔히 사용한다.

 

 

필드 이름에 대한 문법 규칙은 클래스, 인터페이스, 메서드 이름에 비해 덜 명확하고 덜 중요하다. API 설계를 잘 했다면 필드가 직접 노출될일이 거의 없기 때문이다. 

 

 

 

 

 

 

 

728x90
반응형

댓글