Java 공부 40일차(래퍼, Class 클래스란?)1편

임선구·2025년 3월 12일

몸 비틀며 Java

목록 보기
41/58

오늘의 잔디


오늘의 공부 내일은 공강이니까 더 오래 해야지


래퍼 클래스 - 기본형의 한계1

기본형의 한계

자바는 객체 지향 언어이다. 그런데 자바 안에 객체가 아닌 것이 있다. 바로 int , double 같은 기본형(Primitive Type)이다.
기본형은 객체가 아니기 때문에 다음과 같은 한계가 있다.

  • 객체가 아님: 기본형 데이터는 객체가 아니기 때문에, 객체 지향 프로그래밍의 장점을 살릴 수 없다. 예를 들어 객체는 유용한 메서드를 제공할 수 있는데, 기본형은 객체가 아니므로 메서드를 제공할 수 없다.
    • 추가로 객체 참조가 필요한 컬렉션 프레임워크를 사용할 수 없다. 그리고 제네릭도 사용할 수 없다. (이 부분은 뒤에서 설명한다.)
  • null 값을 가질 수 없음: 기본형 데이터 타입은 null 값을 가질 수 없다. 때로는 데이터가 없음 이라는 상태를 나타내야 할 필요가 있는데, 기본형은 항상 값을 가지기 때문에 이런 표현을 할 수 없다.

기본형의 한계를 이해하기 위해, 두 값을 비교해서 다음과 같은 결과를 출력하는 간단한 코드를 작성해보자.

  • 왼쪽의 값이 더 작다 -1
  • 두 값이 같다 0
  • 왼쪽의 값이 더 크다 1
package lang.wrapper;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;
 }
 }
}

실행 결과

i1 = 1
i2 = 0
i3 = -1

여기서는 value 와 비교 대상 값을 compareTo() 라는 외부 메서드를 사용해서 비교한다. 그런데 자기 자신인
value 와 다른 값을 연산하는 것이기 때문에 항상 자기 자신의 값인 value 가 사용된다. 이런 경우 만약 value 가 객체라면 value 객체 스스로 자기 자신의 값과 다른 값을 비교하는 메서드를 만드는 것이 더 유용할 것이다.

직접 만든 래퍼 클래스

int 를 클래스로 만들어보자. int 는 클래스가 아니지만, int 값을 가지고 클래스를 만들면 된다. 다음 코드는 마치 int 를 클래스로 감싸서 만드는 것 처럼 보인다. 이렇게 특정 기본형을 감싸서(Wrap) 만드는 클래스를 래퍼 클래스(Wrapper class)라 한다.

package lang.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); //숫자를 문자로 변경
 }
}
  • MyIntegerint value 라는 단순한 기본형 변수를 하나 가지고 있다.
  • 그리고 이 기본형 변수를 편리하게 사용하도록 다양한 메서드를 제공한다.
  • 앞에서 본 compareTo() 메서드를 클래스 내부로 캡슐화 했다.
  • 이 클래스는 불변으로 설계했다.

MyInteger 클래스는 단순한 데이터 조각인 int 를 내부에 품고, 메서드를 통해 다양한 기능을 추가했다. 덕분에 데이터 조각에 불과한 intMyInteger 를 통해 객체로 다룰 수 있게 되었다.

package lang.wrapper;
public class MyIntegerMethodMain1 {
 public static void main(String[] args) {
 MyInteger myInteger = new MyInteger(10);
 int i1 = myInteger.compareTo(5);
 int i2 = myInteger.compareTo(10);
 int i3 = myInteger.compareTo(20);
 System.out.println("i1 = " + i1);
 System.out.println("i2 = " + i2);
 System.out.println("i3 = " + i3);
 }
}

실행 결과

i1 = 1
i2 = 0
i3 = -1
  • myInteger.compareTo() 는 자기 자신의 값을 외부의 값과 비교한다.
  • MyInteger 는 객체이므로 자신이 가진 메서드를 편리하게 호출할 수 있다.
  • 참고로 int 는 기본형이기 때문에 스스로 메서드를 가질 수 없다.

래퍼 클래스 - 기본형의 한계2

기본형과 null

기본형은 항상 값을 가져야 한다. 하지만 때로는 데이터가 '없음'이라는 상태가 필요할 수 있다.
다음 코드를 작성해보자.

package lang.wrapper;
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));
 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;
 }
}
  • findValue() 는 배열에 찾는 값이 있으면 해당 값을 반환하고, 찾는 값이 없으면 -1 을 반환한다.
  • findValue() 는 결과로 int 를 반환한다. int 와 같은 기본형은 항상 값이 있어야 한다. 여기서도 값을 반환할 때 값을 찾지 못하면 숫자 중에 하나를 반환해야 하는데 보통 -1 또는 0 을 사용한다.

실행 결과

-1
0
1
-1

실행 결과를 보면 입력값이 -1 일 때 -1 을 반환한다. 그런데 배열에 없는 값인 100 을 입력해도 같은 -1 을 반환한다.
입력값이 -1 일 때를 생각해보면, 배열에 -1 값이 있어서 -1 을 반환한 것인지, 아니면 -1 값이 없어서 -1을 반환 한 것인지 명확하지 않다.

객체의 경우 데이터가 없다는 null 이라는 명확한 값이 존재한다.
다음 코드를 작성해보자.

package lang.wrapper;
public class MyIntegerNullMain1 { 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)); //-1
 }
 private static MyInteger findValue(MyInteger[] intArr, int target) {
 for (MyInteger myInteger : intArr) {
 if (myInteger.getValue() == target) {
 return myInteger;
 }
 }
 return null;
 }
}

실행 결과

-1
0
1
null
  • 앞서 만든 MyInteger 래퍼 클래스를 사용했다.
  • 실행 결과를 보면 -1 을 입력했을 때는 -1 을 반환한다.
  • 100 을 입력했을 때는 값이 없다는 null 을 반환한다.

기본형은 항상 값이 존재해야 한다. 숫자의 경우 0 , -1 같은 값이라도 항상 존재해야 한다. 반면에 객체인 참조형은 값이 없다는 null 을 사용할 수 있다. 물론 null 값을 반환하는 경우 잘못하면 NullPointerException 이 발생할 수 있기 때문에 주의해서 사용해야 한다.

profile
끝까지 가면 내가 다 이겨

0개의 댓글