Spring boot로 프로젝트를 하다보니, 정수형 변수로 Long을 자주 사용하게 되었습니다. 그러다 for loop에서 보통 int를 사용하다가 long을 사용하게 되었는데, long형을 사용했을 때 발생하는 문제가 없나?라는 고민을 시작으로 몇가지 알아본 사실을 적어보려 합니다.
Long과 long의 관계
long은 JAVA의 원시타입인 변수타입이고, Long은 long을 다루는 객체를 의미합니다. 이처럼 원시타입을 객체로 다루기위해 사용하는 클래스를 Wrapper 클래스라고 합니다. 원시타입을 Wrapper 클래스인 참조타입으로 만드는 것을 boxing, 그 반대를 unboxing이라고 합니다.
원시타입과 참조타입인 객체는 확연하게 분리되어야하는데, 제가 생각하는 것보다 두 경계가 크지 않았습니다. 예를 들면, 아래와 같이 사용이 가능합니다.
class Test{
public Long getLongPrimitive(){
return (long) 1;
}
public Long getLongNoConstructor(){
Long l = (long) 1;
return l;
}
}
반환 타입이 참조타입 Long인데 원시타입 long으로 반환이 가능하고, Long은 생성자없이 long값을 대입하여 초기화합니다. Intellij에서 new Long((long)1)로 생성자를 사용할 경우, 도움말에서 deprecated되었다는 내용을 볼 수 있습니다.
for loop에서 long 사용
for(long l=0; l<100; l++){
System.out.println(l);
}
long형 증감변수를 사용하니 타입캐스팅으로 인한 오류에 대해 한 번 생각해보게 되었습니다. 위 코드에서 두 가지에 대해 의문이 있었는데요. 첫 번째는 조건식으로, JAVA에서 리터럴은 int형이니 long과 int가 비교연산을 하게됩니다. 두 번째는 증감식으로, 증감연산자도 1이 더해질 때 int로 취급될 수 있지 않을까라는 생각을 했습니다.
결론은 문제 없습니다. 연산에 대해 서로 타입이 다를 때 자동 타입캐스팅(promotion)은 더 큰 타입형, 즉 int가 long형으로 바뀌어 데이터의 손실이 없습니다. 증감연산자에 대해 정보를 찾진 못했지만, 적어도 테스트해본 결과 정상적으로 동작하는 것을 확인했습니다.
원시타입 확인 방법
JAVA의 원시타입과 참조타입의 차이는 null과 제너릭입니다. 원시타입은 null이 아닌 쓰레기값을 가지기 때문에 null인지 확인하기 어려울 수 있고, ArrayList와 같은 제너릭에 사용될 수 없습니다.
그리고 JAVA는 원시타입을 확인할 방법이 없다고 하네요. 속도를 고려하지 않는다면 여러모로 객체를 사용하는게 편하고 안전할 듯 합니다.
'CS > 언어' 카테고리의 다른 글
[JAVA] Hash와 Thread-Safe (0) | 2022.01.19 |
---|---|
[JAVA] ArrayList에서 특정 값을 가진 원소들 찾기 (0) | 2022.01.14 |
[JAVA] 자바의 다중상속 (0) | 2022.01.11 |
[JAVA] POJO(Plain Old Java Object) (0) | 2022.01.06 |
[Python] Pypy와 CPython (구현체) (0) | 2021.10.01 |