java-squid/effective-java

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

Closed this issue · 7 comments

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

박싱된 기본 타입은 값 + 식별성(identity)를 가진다..

  • 여기서 말하는 identity는 해당 인스턴스가 올라가있는 메모리 주소값..? 이라고 이해하면 될까요?

저도 대충 그렇게 이해했습니다.

책에서 지적하는 위험성 (identity 나, null 값에 대한 위험성) 은
기본 연산자를 사용하지 않고 eqauls 함수나 compare 함수를 대신 사용함으로써 피할 수 있다고,
책에서 나오기는 하네요.

자바에서 제네릭을 사용하게 되면 어쩔 수 없이 박싱된 기본 타입을 사용할 수 밖에 없을 때가 있는데,
이럴 때 기본 연산자를 금지하고, 철저하게 객체의 함수 콜만을 사용하면 괜찮지 않을까 생각합니다.
(자바가 제네릭에 기본 타입을 지원해주면 좋을텐데 ㅠ.ㅠ)

단이 저의 프로젝트에서 코드 리뷰해주실 때 primitive class, wrapper class 기준점 입니다.
image

@102092

  • 여기서 말하는 identity는 해당 인스턴스가 올라가있는 메모리 주소값..? 이라고 이해하면 될까요?

맞습니다. 하지만 코드 예시를보면 Integer.valueOf(i) == Integer.valueOf(j)의 값이 true라고 나옵니다. 즉 둘의 메모리 주소값이 같다고 나오는데 그 이유는 IntegerCache에 있습니다.

public static Integer valueOf(int i) {
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}

@ghojeong

자바에서 제네릭을 사용하게 되면 어쩔 수 없이 박싱된 기본 타입을 사용할 수 밖에 없을 때가 있는데,
이럴 때 기본 연산자를 금지하고, 철저하게 객체의 함수 콜만을 사용하면 괜찮지 않을까 생각합니다.

예를 들어 List가 있고 리스트 안에 들어있는 원소에 대한 연산을 하고 싶다면 기본 연산자를 피할 수는 없겠죠. 박싱된 타입은 뭐라도 하려면 일딴 언박싱을 해야돼서... 자바 제너릭의 원천적인 문제인지라 ㅠ 정말 성능이 중요한 상황이라면 int[] 쓰는 수 밖에...

(자바가 제네릭에 기본 타입을 지원해주면 좋을텐데 ㅠ.ㅠ)

이건 Project Valhalla에서 건드려 보고는 있는 거 같은데 언제쯤 나오려나...

@kses1010

  1. OptionalInt, OptionalLong 등을 사용해서 쿼리 반환값이 없는 경우를 핸들링 할 수도 있지 않을까요.
  2. @RequestParam이나 @RequestBody의 경우에도 빈 값을 받는 경우 custom serializer, deserializer을 통해서
    • enum 값으로 지정해준다거나 (예를 들어 int count = Product.DEFAULT_COUNT)
    • 역시 OptionalInt, OptionalLong 등으로 처리할 수 있을텐데
      좀 귀찮기는 한데 데 빈 값이라고 그냥 null로 해놓으면 나중에 실수를 할 수도 있고 베스트 프랙티스인지는 모르겠습니다.
  3. DTO도 null value 들고 있을 수 있으니 DAO / Entity vs DTO 식으로 나누는 게 맞나? 싶네요.

primitive 사용을 나눈게 아니라 허용되는 경우니 DTO도 null value 들 수 있죠.
primitive의 기본값

  • boolean: false
  • byte: 0
  • short: 0
  • int: 0
  • long: 0L
  • float: 0.0F
  • double: 0.0
  • char: '\u0000'