개발 기록

[이펙티브 자바] 아이템 59,60 본문

JAVA

[이펙티브 자바] 아이템 59,60

수염차 2025. 5. 27. 21:30

## 정확한 답이 필요하다면 float 과 double 은 피하라

 

### float, double

  • 과학과 공한 계산용으로 설계된 데이터 타입이다.
  • 이진 부동소수점 연산에 쓰이며, 넓은 범위의 수를 빠르게 정밀한 근사치로 계산하도록 설계되었다.
  • 정확한 결과가 필요한 금융 관련 계산과는 어울리지 않는다.
    • 1.03 - 0.42의 결과를 0.6100000000001을 출력한다.

### BigDecimal, int, long 사용

- BigDecimal  : 사용하기 불편하고 느리다는 단점이 있다.

public static void main(String[] args) {
    final BigDecimal TEN_CENTS = new BigDecimal(".10");
    int itemsBought = 0;
    BigDecimal funds = new BigDecimal("1.00");

    for (BigDecimal price = TEN_CENTS; funds.compareTo(price) >= 0;
         price = price.add(TEN_CENTS)) {
        funds = funds.subtract(price);
        itemsBought++;
    }
    System.out.println(itemsBought + "개 구입");
    System.out.println("잔돈(달러): " + funds);
}

 

- int , long : 값의 크기가 제한되고 소수점을 직접 관리해야 한다는 단점이 있다.

public static void main(String[] args) {
    int itemsBought = 0;
    int funds = 100;
    
    for (int price = 10; funds >= price; price += 10) {
        funds -= price;
        itemsBought++;
    }
    System.out.println(itemsBought + "개 구입");
    System.out.println("잔돈(센트): " + funds);
}

 

### 핵심정리

정확한 답이 필요한 계산에는 float나 double을 피하라.

소수점 추적은 시스템에 맡기고, 코딩 시의 불편함이나 성능 저하를 신경 쓰지 않겠다면 BigDecimal을 사용하라. 

BigDecimal이 제공하는 여덟 가지 반올림 모드를 이용하여 반올림을 완벽히 제어할 수 있다. 

법으로 정해진 반올림을 수행해야 하는 비즈니스 계산에서 아주 편리한 기능이다. 

 

반면, 성능이 중요하고 소수점을 직접 추적할 수 있고 숫자가 너무 크지 않다면 int나 long을 사용하라. 

숫자를 아홉 자리 십진수로 표현할 수 있다면 int를 사용하고, 열여덟 자리 십진수로 표현할 수 있다면 long을 사용하라. 

열여덟 자리를 넘어가면BigDecimal을 사용해야 한다.

 


## 박싱된 기본 타입보다는 기본 타입을 사용하라

 

### 자바의 데이터 타입

  1. 기본 타입 : int, double, boolean..
  2. 참조 타입 : Integer, Double, Boolean

### 기본 타입과 박싱된 기본 타입의 차이

1. 기본 타입은 값만 가지고 있으나, 박싱된 기본 타입은 값에 대해 식별성이라는 속성을 가진다. 즉, 박싱된 기본 타입의 두 인스턴스는 값이 같아도 다르다고 식별될 수 있다.

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

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

 

### 잘 못 사용시 발생하는 오류

1. 박싱된 기본 타입에 == 연산자를 사용하면 오류가 일어난다.

2. 기본 타입과 박싱된 기본 타입을 혼용한 연산에서는 박싱된 기본 타입의 박싱이 자동으로 풀린다. 

그리고 null 참조를 언박싱하면 NullPointerException이 발생한다.

3. 오류나 경고 없이 컴파일되지만, 박싱과 언박싱이 반복해서 일어나면 체감될 정도로 성능이 느려진다.

ex. sum을 언박싱해서 long 값을 꺼내고 i와 더한 후 다시 박싱해서 Long 객체를 새로 만든다.

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 += i; 내부처리
sum = Long.valueOf(sum.longValue() + i);

 

### 박싱된 기본 타입을 써야하는 경우

  • 컬렉션의 원소, 키, 값으로 쓴다. 기본 타입을 담을 수 없다. 
  • 리플렉션을 통해 메서드를 호출할 때도 박싱된 기본 타입을 사용해야 한다.

 

### 핵심정리

기본 타입과 박싱된 기본 타입 중 하나를 선택해야 한다면 가능하면 기본 타입을 사용하라. 

기본 타입은 간단하고 빠르다. 박싱된 기본 타입을 써야 한다면 주의를 기울이자. 

오토박싱이 박싱된 기본 타입을 사용할 때의 번거로움을 줄여주지만, 그 위험까지 없애주지는 않는다. 

두 박싱된 기본 타입을 = 연산자로 비교한다면 식별성 비교가 이뤄지는데, 이는 여러분이 원한 게 아닐 가능성이 크다. 

같은 연산에서 기본 타입과 박싱된 기본타입을 혼용하면 언박싱이 이뤄지며, 언박싱 과정에서 NullPointerException을 던질
수 있다. 

마지막으로, 기본 타입을 박싱하는 작업은 필요 없는 객체를 생성하는 부작용을 나을 수 있다.

'JAVA' 카테고리의 다른 글

[이펙티브 자바] 아이템 64  (1) 2025.06.09
[이펙티브 자바] 아이템 62,63  (0) 2025.06.09
[이펙티브 자바] 아이템 58,59  (0) 2025.05.27
[이펙티브 자바] 아이템 47  (0) 2025.05.06
[이펙티브 자바] 아이템 57  (0) 2025.05.06
Comments