티스토리 뷰

728x90
반응형

목차

     

    Summary

     

    기본형과 참조형 데이터 타입의 차이에 대해서만 선 요약하고 들어간다.

     

    요약 이후의 글은 둘의 차이 뿐 아니라 각각의 특성에 대해서도 조금 더 다루고 있다.

     

      Primitive Variables Reference Variables
    개수 8 무제한(기본형을 제외한 전부)
    크기 1, 2, 4, 8byte(타입마다 다름) 4, 8byte(JVM에 따라 다름)
    저장 데이터 데이터 값 데이터의 주소값
    데이터 저장 위치 Call Stack Heap
    산술연산 가능 불가능
    null 값 불가능 가능
    비교 연산자 == equals()

     

    Primitive Variables

     

    자바는 아래의 8가지 기본형 타입을 제공한다.

     

      타입 할당되는 메모리 크기 기본값 표현 범위
    논리형 boolean 1 byte false true, false
    정수형 byte 1 byte 0 -128 ~ 127
    short 2 byte 0 -32,768 ~ 32,767
    int(기본) 4 byte 0 -2,147,483,648 ~ 2,147,483,647
    long 8 byte 0L -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807
    실수형 float 4 byte 0.0F (3.4 X 10-38) ~ (3.4 X 1038) 근사값
    double(기본) 8 byte 0.0 (1.7 X 10-308) ~ (1.7 X 10308) 근사값
    문자형 char 2 byte (유니코드) '\u0000' 0 ~ 65,535

    기본형 타입은 아래와 같은 특징을 지니며,

     

    • 메모리에 값 자체를 저장
    • 산술 계산 가능
    • null 값을 가질 수 없음(=객체 타입이 아님)

    표현 범위보다 큰 값을 저장하려고 하면 형 변환을 요구하는 에러가 난다.

    byte i = 128;
    java: incompatible types: possible lossy conversion from int to byte

     

    Type Conversion

     

    형 변환의 경우 표현 범위가 작은 변수 -> 큰 변수의 변환은 컴파일러에 의해 자동으로 이루어지며,

     

    (byte < short < int < long < float < double)

    public class PrimitivePractice {
        public static void main(String[] args) {
    
            byte a = 1;
            short b = a;
            int c = b;
            long d = c;
            float e = d;
            double f = e;
    
            System.out.println(f);
        }
    }
    1.0

    반대의 경우 타입을 명시하지 않으면 에러가 난다.

    public class PrimitivePractice {
        public static void main(String[] args) {
    
            int a = 1;
    //        short b = a; // 에러
            short b = (short) a;
    
            System.out.println(b);
        }
    }
    1

    위와 같은 명시적 형 변환의 경우, 오버플로우 혹은 언더플로우의 가능성이 있으므로 주의해야 한다.

    public class PrimitivePractice {
        public static void main(String[] args) {
    
            int a = 32768;
            short b = (short) a;
    
            System.out.println(b);
        }
    }
    -32768 // 오버플로우 발생

    또한 연산 결과를 담을 때 역시 표현 범위를 넘어서면 오버플로우가 일어나게 된다.

    public class PrimitivePractice {
        public static void main(String[] args) {
    
            byte i = 127;
    
            i++;
    
            System.out.println(i);
        }
    }
    -128

    마지막으로 boolean 타입의 경우 다른 타입으로의 형 변환이 불가능하며,

     

    char 타입의 경우 음수 범위를 다룰 수 없으므로 같은 크기의 short로 형 변환 시 반드시 명시해주어야 한다.

    public class PrimitivePractice {
        public static void main(String[] args) {
    
            char a = 'a';
    //        short b = a; // 에러
            short b = (short) a;
    
            System.out.println(b);
        }
    }
    97

     

    Floating Point & Accuracy Problem

     

    이어서 실수형 타입 float과 double에 대해서 조금 더 알아보자.

     

    두 데이터 타입은 각각 실수를 부동소수점 방식으로 나타내 근사치의 계산을 빠르게 하기 위한 자료형이다.

     

    여기서 부동소수점 방식이란 아래와 같은 표현 방식을 말하며,

     

    가수(Significand)부분의 저장 용량에 따라 데이터 타입의 정확도가 정해진다.

     

    물론 실제 컴퓨터에 데이터가 저장될 때는 위와 같은 십진수가 아니라 이진수의 형태로 저장되며,

     

    타입별 가수와 지수(Exponent)에 할당되는 메모리 및 정확도는 아래와 같다.

     

    타입 부호 지수 가수 유효 자릿수
    float(32bit) 1bit 8bit 23bit 7
    double(32bit) 1bit 11bit 52bit 16

    또한 앞서 말한 바와 같이 어디까지나 근삿값에 대한 계산이므로 언제나 오차가 존재할 가능성이 있으며

    System.out.println(0.1f * 0.1f);
    0.010000001

    교환 법칙은 항상 성립하지만 결합 법칙과 분배 법칙은 항상 성립하지는 않는다는 특성이 있다.

     

    참고로 오차 없이 큰 수를 다루고 싶은 경우에는 BigDecimal(실수형), BigInteger(정수형) 등의 타입을 사용하면 된다.

     

    2022.10.09 - [Development/Java] - [Java]무한히 큰 숫자 다루기, BigInteger

     

    [Java]무한히 큰 숫자 다루기, BigInteger

    자바의 기본 자료형인 int와 long은 아래와 같은 범위의 수를 저장할 수 있다. Type Range int -2,147,483,648 ~ 2,147,483,647 (약 21억) long -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807 (약 900..

    gnidinger.tistory.com

     

    Wrapper Classes

     

    계속해서 기본형을 객체 타입으로 이용해 null을 저장하고 싶으면 래퍼(Wrapper) 클래스를 사용해야 한다.

    public class PrimitivePractice {
        public static void main(String[] args) {
    
            Byte i = null;
    
            System.out.println(i);
        }
    }
    null

    여기서 래퍼 클래스란 이름 그대로 기본형 데이터 타입을 객체 형태의 타입으로 포장하는 클래스를 가리키며,

     

    기본형을 래핑하는 과정을 박싱(Boxing), 반대 과정을 언박싱(Unboxing)이라 부른다.

     

    각 기본형에 대한 래퍼 클래스는 아래와 같다.

    Primitive Types Wrapper Classes
    boolean Boolean
    byte Byte
    short Short
    int Integer
    long Long
    float Float
    double Double
    char Character

    끝으로 JDK 1.5 이전까지는 박싱과 언박싱을 일일이 입력해주어야 했으나

     

    지금은 자동 박싱/언박싱(Auto Boxing/Unboxing)이 지원되므로 편하게 형 변환을 할 수 있다.

    public class PrimitivePractice {
        public static void main(String[] args) {
    
            byte i = 1;
    
            Byte j = i;
    
            System.out.println(j);
        }
    }
    1

     

    Reference Variables

     

    참조형 데이터 타입은 위에서 알아본 기본형을 제외한 자바의 모든 타입을 가리킨다.

     

    많이 쓰이는 타입은 아래와 같으며,

     

    타입 예시 기본값 할당되는 메모리 크기
    Array int[] arr = new int[5]; 0 4byte(32bit JVM)
    /
    8byte(64bit JVM)
    →데이터 주소를 저장
    Enumeration   Null
    Class String str = "String";
    Member member = new Member();
    Null
    Interface   Null

    클래스에서 볼 수 있듯이 사용자 정의 타입도 포함한다.

     

    이어서 참조형 데이터 타입은 기본형 데이터 타입과 달리 다음과 같은 특징을 갖는다.

     

    • 메모리에 데이터 주소(참조값)를 저장 → 실제 값은 힙 메모리에 위치
    • 산술 연산 불가능
    • null 값을 가질 수 있음 → NPE에 대한 대비 및 처리 필요

    추가로 앞서 알아봤던 박싱 과정 역시 기본형을 참조형으로 변환해주기 때문에 산술연산이 불가능해야 하지만

     

    자동 박싱/언박싱 덕분에 연산이 가능하다는 예외적인 특징을 가지고 있다.

     

    여기서 잊지 말아야 할 점은 참조형은 데이터 자체가 아닌 주소값을 저장하기 때문에

     

    비교 연산자(특히 ==)를 사용할 때 주의해야 한다는 것이다.

    public class ReferencePractice {
        public static void main(String[] args) {
    
            String a = "abc";
            String b = "abc";
            String c = new String("abc");
    
            System.out.println(a);
            System.out.println(b);
            System.out.println(c);
            System.out.println(a == b); // true
            System.out.println(a == c); // false
            System.out.println(a.equals(c)); // true
    
        }
    }
    abc
    abc
    abc
    true
    false
    true

    같은 "abc" 값을 가졌지만 a와 c는 다른 주소를 가리키고 있으므로 false를 리턴하게 된다.

     

    따라서 참조형을 다룰 땐 데이터 값을 비교해주는 equals()메서드를 사용하는 습관을 들이는 것이 좋다.

    반응형
    댓글
    공지사항
    최근에 올라온 글
    최근에 달린 댓글
    Total
    Today
    Yesterday
    링크
    «   2024/09   »
    1 2 3 4 5 6 7
    8 9 10 11 12 13 14
    15 16 17 18 19 20 21
    22 23 24 25 26 27 28
    29 30
    글 보관함