JAVA

[Java] 래퍼 클래스

songsua 2025. 1. 16. 20:45

Wrapper Class: 기본형을 감싸서 만드는 클래스를 래퍼 클래스라고 한다.

 

  • 기본 타입: int, double, boolean, 등등
  • Wrapper 클래스: Integer, Double, Boolean, 등등

 

기본형 클래스 : int, double 과 같은 기본형 타입이다. 기본형은 객체가 아니기 때문에 메서드를 제공해 줄 수 없다.

그리고 기본형은 null 값을 가질 수 없다. 기본형은 항상 값을 가지기 때문에 null 값을 가질 수 없다.

 

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);

 

외부 메서드인 compareTo() 를 사용한다. 

항사 value 자기 자신 값을 사용하여 비교를 하는 데, value 값 자체가 다른 값과 메서드를 이용해 비교하는 것이 유용할 것이다.

하지만 value는 단순히 기본형이기 때문에 "value.compareTo()" 를 사용하는 것이 불가능하다.

 

이러한 기본형을 이용한 메서드를 만들려면, int 를 클래스로 만들면 된다.

int는 클래스가 아니지만, int 값을 가지고 클래스를 만들면 된다.

아래처럼 마치 int클래스를 감싸서 만드는데, 이렇게 특정 기본형을 감싸서 만드는 클래스를 래퍼 클래스라고 한다.

 

package Wrapper;

public class MyInteger {
    private final int value;
    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);
    }
}

 

위의 코드를 보면 클래스 내부에 메서드를 캡슐화하였다.

final을 이용하여 이 클래스는 불변으로 설계하였다.

package Wrapper;

public class MyIntegerMain {
    public static void main(String[] args) {
        MyInteger myInteger = new MyInteger(10);
        int answer1 = myInteger.compareTo(20);
        int answer2 = myInteger.compareTo(5);

        System.out.println(answer1);
        System.out.println(answer2);
    }

}

 

int answer1 = myInteger.compareTo(20);
int answer2 = myInteger.compareTo(5);

이는 자기 자신의 값을 외부의 값과 비교한다.

MyInteger은 객체이기 때문에 자신이 가진 메서드를 편리하게 호출할 수있다.

 

기본형과 Null

기본형은 항상 값을 가지고 있어야한다. 

하지만 때로는 값이 없어야할 때가 있을 수 있다.

package Wrapper;

public class MyIntegerMain1 {
    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));
        System.out.println(findValue(intArr, 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;
    }
}
//이런식으로 존재하지 않을때 -1 return 하도록 설계했는데, 존재하지 않을 때도 int로 출력되도록 설계해야한다.

 

그렇다면 객체를 사용하여 null 을 출력하게 만들면 된다.

package Wrapper;

public class MyIntegerMain1 {
    public static void main(String[] args) {
        MyInteger[] intArr = {new MyInteger(1), new MyInteger(0), new MyInteger(1)};
        System.out.println(findValue(intArr, -1)); //-1
        System.out.println(findValue(intArr, 0));
        System.out.println(findValue(intArr, 1));
        System.out.println(findValue(intArr, 100)); //-1
    }
    private static MyInteger findValue(MyInteger[] intArr, int target) {
        for (MyInteger myInteger : intArr) {
            if (myInteger.getValue() == target) {
                return myInteger;
            }
        }
        return null;
    }
}

 

null
0
1
null

 

 

자바 래퍼 클래스

박싱(Boxing) : 기본형 래퍼 클래스로 변경하는 것을 마치 박스에 물건을 넣는것 같아, 박싱이라고 한다.

intValue() - 언박싱(UnBoxing) : 래퍼 클래스에 들어있는 기본형 값을 다시 꺼내는 메서드이다.

오토박싱(AutoBoxing) : 기본 타입을 Wrapper 클래스 객체로 자동 변환하는 것

//primitive --> wrapper
int value = 7;
Integer boxedValue = Integer.valueOf(value);
//Integer 라는 박스안에 value 7값을 넣었다.
//valueof()사용

//wrapper --> primitive
int unboxedValue = boxedValue.intValue();
//intValue() 사용

박싱 : valueof()

언박싱: xxxValue() 

 

항상 바꾸는 것이 힘들어서 autoboxing 을 출시하였다.

package Wrapper;

public class AutoBoxingMain {
    public static void main(String[] args) {
        int value = 7;
        Integer boxValue = value;

        int unboxValue = boxValue;
        System.out.println(boxValue);
        System.out.println(unboxValue);
    }
}

왜 Autoboxing과 Unboxing이 필요한가?

기본 타입과 객체 타입을 섞어서 사용할 수 있게 만들어준다.

예를 들어, Java의 컬렉션(ArrayList, HashMap)은 객체만 저장할 수 있습니다. Autoboxing이 있으면 기본 타입을 컬렉션에 쉽게 저장할 수 있다.

Integer boxedValue = value; 
//오토 박싱(Auto-boxing)

Integer boxedValue = Integer.valueOf(value); 
//컴파일 단계에서 추가

int unboxedValue = boxedValue; 
//오토 언박싱(Auto-Unboxing) 

int unboxedValue = boxedValue.intValue(); 
//컴파일 단계에서 추가

 

 

주요 메서드

package Wrapper;

public class WrapperUtilsMain {
    public static void main(String[] args) {
        Integer i1 = Integer.valueOf(16);
        // 숫자를 객체로 변환
        Integer i2 = Integer.valueOf("10"); // 문자열을 객체로 변환가능
        // Integer i3 = Integer.parseInt(16);  // 문자열을 숫자형으로 바꾸고 싶을 때 사용 하지만 "" 로 string 처럼 사용 해야한다.
        Integer i3 = Integer.parseInt("16");

        //비교
        int compareResult = i1.compareTo(20);
        System.out.println("비교 =" + compareResult);

        //산술연산
        System.out.println("sum : " + Integer.sum(i1, i2));  //i2가 string 인대도 26으로 출련된다 
        // 이는 객체에서 자동으로 unboxing 하여 int 로 바꾼 다음에, sum 한다.
    }
}

 

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

parselnt() VS value Of()

  • value of("10") 는 래퍼 타입을 반환한다
  • parseInt("10") 은 기본형을 반환한다.

성능은 래퍼클래스보다 기본 클래스가 더 빠르기는 하다.
하지만 유지보수  vs 최적화를 고려해야 하는 상황이라면 유지보수 하기 좋은 코드를 먼저 고민해야한다.

 


Class 클래스

class는 클래스의 메타데이터를 다루는데 사용한다. Class 클래스를 통해 개발자는 실행 중인 자바 애플리케이션 내에서 필요한 클래스의 속성과 메서드에 대한 정보를 조회하고 조작할 수 있다.
Class 클래스의 주요 기능 

  • 타입 정보 얻기: 클래스의 이름, 슈퍼클래스, 인터페이스, 접근 제한자 등과 같은 정보를 조회할 수 있다.
  • 리플렉션 : 클래스에 정의된 메서드, 필드, 생성자 등을 조회하고 이들을 통해 객체 인스턴스를 생성하거나 메서드를 호출하는 등의 작업을 할 수 있다. 쉽게 말해, "코드가 자기 자신을 들여다보고 조작할 수 있는 기능" 평소에는 new 키워드로 객체를 생성하거나, 메서드()를 직접 호출하지만, 리플렉션을 쓰면 "클래스 이름만 문자열로 받아서 동적으로 객체를 만들고 메서드를 실행"
  •  동적 로딩과 생성 : Class,forName() 메서드를 사용하여 클래스를 동적으로 로드하고, newInstance() 메서드를 통해 새로운 인스턴스를 생성할 수 있다
  • 애노테이션 처리: 클래스에 적용된 애노테이션을 조회하고 처리하는 기능을 제공한다.예를 들어, String.class는 String 클래스에 대한 Class 객체를 나타내며 이를 통해 String 클래스에 대한 메타데이터를 조회하거나 조작할 수 있다.

예)

import java.lang.reflect.Method;

public class ReflectionExample {
    public static void main(String[] args) {
        Class<?> clazz = Hello.class; // Hello 클래스의 Class 객체 가져오기

        // 클래스의 모든 메서드 가져오기
        Method[] methods = clazz.getDeclaredMethods();

        System.out.println("메서드 목록:");
        for (Method method : methods) {
            System.out.println(method.getName());
        }
    }
}

 

메서드 목록:
sayHello






문제풀이

 

로또 번호 자동 생성기

로또 번호 1~45 사이의 숫자 6개를 뽑고, 중복은 안된다.
실행될 때마다 결과가 달라져야 한다.

package thread;

import java.util.Random;

public class RandomTest {
    private final Random random = new Random();
    private int[] lottoNumbers;
    private int counter;

    public int[] generate() {
        //generate 는 번호 생성된 것을 배열에 반환하는 것
        lottoNumbers = new int[6];
        counter = 0;

        while (counter < 6) {
            int num = random.nextInt(45) + 1;
            //1 ~ 46까지 숫자를 출력
            if (isUnique(num)) {
                //true이면,
                lottoNumbers[counter] = num;
                //중복이 아닐 경우에만 카운터가 증가하도록 해야한다.
                counter++;
            }
        }
        return lottoNumbers;
    }

    private boolean isUnique(int num) {
        for (int i = 0; i < counter; i++) {
            if(num == lottoNumbers[i]) {
                return false;
            }
        }
        return true;

    }

}
package thread;

public class LottoMain {
    public static void main(String[] args) {
        RandomTest rand = new RandomTest();
        //이거 코드 다시보기
        int [] lottonum = rand.generate();

        System.out.println("로또 번호");
        for (int lottonumber : lottonum) {
            System.out.println(lottonumber);
        }
    }
}