[JAVA] 래퍼 클래스

나의 개발 일지·2024년 12월 8일

JAVA

목록 보기
9/11

우선, 글을 작성하기 전 이 글의 모든 내용은 김영한님의 JAVA 강의를 바탕으로 함을 알립니다.

💡래퍼 클래스

기본형의 한계

객체 지향 언어인 Java가 제공하는 기본형(Primitive Type)은 객체가 아니기에 두 가지의 한계점이 존재한다.

◻️ 객체가 아니다.

  • 객체는 상태(필드)와 기능(메서드)를 통해 객체 지향적 프로그래밍을 장점을 살릴 수 있다.
public class MyIntegerMethodMain0 {

    public static void main(String[] args) {
        int value = 10;
        int i1 = compareTo(value,5);
        int i2 = compareTo(value,10);
        int i3 = compareTo(value,20);
        System.out.println("i1 = " + i1);
        System.out.println("i2 = " + i2);
        System.out.println("i3  = " + i3);
        
    }

    public static int compareTo(int value, int target) {
        if (value < target) {
            return -1;
        } else if (value > target) {
            return 1;
        } else {
            return 0;
        }
    }
}

위의 예제를 보면 compareTo메서드를 통해 value와 다른 정수를 비교하여 비교에 따른 반환값을 반환하여 출력한다. 비교 대상을 보면 value와 다른 정수들이고 value는 계속해서 사용되는 것을 알 수 있다. 만약 value가 기본형이 아닌 참조형이었다면 value객체가 자기 자신과 다른 정수를 비교하는 compareTo메서드를 만드는 것이 객체 지향적이었을 것이다.

public class MyInteger {

    private final int value; // int 타입의 기본형 변수를 하나 갖고 있고 클래스화 했기에 유용한 메서드를 만들어서 사용 가능

    public MyInteger(int value) {
        this.value = value;
    }

    public int getValue() {
        return value;
    }

    public int compareTo(int target) {
        if (value < target) {
            return -1;
        } else if (value > target) {
            return 1;
        } else {
            return 0;
        }
    }

    @Override
    public String toString() {
        return String.valueOf(value);
    }
}

위의 MyInteger클래스처럼 기본형을 참조형으로 만들었을 경우 메서드를 통해 자기 자신의 값(value)와 다른 정수를 비교할 수 있다. 즉, 객체 입장에서 문제를 해결할 수 있다.

◻️ null 값을 가질 수 없음

  • 기본형은 없음의 개념을 표현 할 수 없다. 기본형은 항상 을 가지기 때문에 없음을 표현할 수 없다.
    다음 예제를 살펴보자
public class MyIntegerNullMain0 {

    public static void main(String[] args) {
        int[] intArr = {-1, 0, 1, 2, 3};
        System.out.println(findValue(intArr,-1)); //-1
        System.out.println(findValue(intArr,0)); //0
        System.out.println(findValue(intArr,1)); //1
        System.out.println(findValue(intArr,100)); //-1
    }

    private static int findValue(int[] intArr, int target) {
        for (int value : intArr) {
            if (value == target) {
                return value;
            }
        }
        return -1; // int는 기본형으로 무조건 값이 있어야한다.
    }
}

위의 예제는 findValue메서드를 통해 intArr에 존재하는 정수와 target정수를 비교해서 동일하면 정수를 반환하고 다르면 -1을 반환하는 예제이다. 근데 여기서 문제점이 발생한다.

System.out.println(findValue(intArr,-1)); //-1

이 부분을 보면 target이 -1이고 intArr배열은 -1을 원소로 갖고 있다. findValue메서드에 의해 결과가 -1이 반환되었다면 value가 -1이어서 target과 동일하여 반환된 것인지, value가 -1이 아니어서 target과 다르기에 반환된 것인지 어떻게 알까? 기본형이기에 불가능한 것이다. 참조형을 살펴보자.

public class MyIntegerNullMain {

    public static void main(String[] args) {
        MyInteger[] intArr = {new MyInteger(-1), new MyInteger(0), new MyInteger(1)};
        System.out.println(findValue(intArr, -1));
        System.out.println(findValue(intArr, 0));
        System.out.println(findValue(intArr, 1));
        System.out.println(findValue(intArr, 100));

    }

    private static MyInteger findValue(MyInteger[] intArr, int target) { // 래퍼 클래스 사용
        for (MyInteger myInteger : intArr) {
            if (myInteger.getValue() == target) {
                return myInteger;
            }
        }
        return null; // 래퍼클래스를 통해 참조형으로 바뀌어 null 사용 가능
    }
}

참조형의 경우 Null을 사용할 수 있기에 조건에 부합하지 않는경우 Null을 통해 표현이 가능하다.

래퍼 클래스(Wrapper class)란

기본형은 객체가 아니기에 '자기 자신'입장에서 특정 기능을 제공 할 수 없다는 것과 값이 '없음'을 표현할 수 없다는 단점을 갖는다. Java는 기본형의 단점을 보완할 수 있는 래퍼 클래스를 제공한다.

Wrap을 직역하면 "포장하다","감싸다"로 해석할 수 있다.

래퍼 클래스기본형객체로 감싸서 객체의 기능을 갖도록 하는 클래스이다. 즉, 기본형의 객체화라고 보면된다.

◻️ 래퍼 클래스 종류

  • byteByte
  • shortShort
  • intInteger
  • longLong
  • floatFloat
  • doubleDouble
  • charCharacter
  • booleanBoolean

◻️ 래퍼 클래스 특징

  1. 불변 객체이다
  2. equals를 통해 동등성 비교를 해야한다

박싱(Boxing)과 언박싱(Unboxing)

  • 박싱(boxing) : 물건을 박스에 넣는 행위, 기본형을 래퍼 클래스로 변경하는 것
  • 언박싱(Unboxing) : 박스의 물건을 꺼내는 행위, 래퍼 클래스를 다시 기본형으로 꺼내는 것
public class WrapperClassMain {

	public static void main(String[] args) {
    	// 박싱(Boxing)
    	Integer newInteger = new Integer(10); // 삭제 예정 -> valueOf() 사용 권장
        Integer integerObj = Integer.valueOf(10); 
        Long longObj = Long.valueOf(100);
        Double doubleObj = Double.valueOf(10.5);
        
        System.out.println("newInteger = " + newInteger); // newInteger = 10
		System.out.println("integerObj = " + integerObj); // integerObj = 10
		System.out.println("longObj = " + longObj); // longObj = 100
		System.out.println("doubleObj = " + doubleObj); // doubleObj = 10.5
        
        // 언박싱(Unboxing)
        System.out.println("내부 값 읽기");
        int intValue = integerObj.intValue(); // intValue = 10
        long longValue = longObj.longValue(); // longObj = 100
        System.out.println("intValue = " + intValue); 
		System.out.println("longObj = " + longValue);
        
        System.out.println("비교");
		System.out.println("==: " + (newInteger == integerObj)); // ==: false
		System.out.println("equals: " + newInteger.equals(integerObj)); // equals: true
    }
}
  • valueOf() - 박싱(Boxing)

    • Integer.valueOf(num)는 단순히 num에 해당하는 정수를 박싱하는 기능뿐만아니라 성능 최적화 기능이 있다.
    • -128~128 범위의 Integer 클래스를 미리 생성하고, 해당 범위의 값이 조회되면 미리 생성된 Integer 객체를 반환한다. 마치 문자열 풀과 비슷하게 미리 생성하고 필요시 제공하는 방식이다.
  • intValue() - 언박싱(Unboxing)

  • 비교는 equals()

    • 래퍼 클래스는 객체이기 때문에 동등성 비교를 통해 비교를 해야한다.

오토 박싱, 오토 언박싱

개발자들에 의해 박싱언박싱의 사용 빈도가 늘며 변환 과정에 있어서 더 나은 편의를 제공하기 위해 오토 박싱오토 언박싱을 지원한다.

오토박싱오토 언박싱valueOf(),intValue()와 같은 메서드를 사용하지 않고 박싱과 언박싱을 진행하는 것이다. 예제를 살펴보자

public class AutoboxingMain2 {

    public static void main(String[] args) {
        //Primitive -> Wrapper ,, boxing
        int value = 7;
//        Integer boxedValue = Integer.valueOf(value);
        Integer boxedValue = value; // 오토 박싱(Auto boxing)

        //Wrapper -> Primitive ,, unboxing
//        int unboxedValue = boxedValue.intValue();
        int unboxedValue = boxedValue; // 오토 언박싱(Auto unboxing)

        System.out.println("boxedValue = " + boxedValue);
        System.out.println("unboxedValue = " + unboxedValue;
     }
}

예제를 보면 오토 박싱과 오토 언박싱은 생성된 래퍼 클래스 객체에 일반 '값'을 저장하는 형태로 진행된다.

Integer boxedValue = value; // 오토 박싱(Auto boxing)
int unboxedValue = boxedValue; // 오토 언박싱(Auto unboxing)

오토 박싱과 오토 언박싱은 컴파일러가 대신 valueOf,xxxValue()의 코드를 추가해주는 기능이다.

래퍼 클래스의 주요 메서드

  • valueOf() : 래퍼 타입 반환, 숫자, 문자열 모두 지원
  • parseInt() : 기본형 타입 반환, 문자열을 기본형으로 변환
  • compareTo() : 내 값과 인수로 넘어온 값을 비교. 내 값이 크면 1, 같으면 0, 작으면 -1을 반환
  • Integer.sum(),Integer.min(),Integer.max() : static메서드, 간단한 사칙연산 수행

0개의 댓글