오늘의 잔디
오늘의 공부 내일은 공강이니까 더 오래 해야지
자바는 객체 지향 언어이다. 그런데 자바 안에 객체가 아닌 것이 있다. 바로 int , double 같은 기본형(Primitive Type)이다.
기본형은 객체가 아니기 때문에 다음과 같은 한계가 있다.
null 값을 가질 수 없다. 때로는 데이터가 없음 이라는 상태를 나타내야 할 필요가 있는데, 기본형은 항상 값을 가지기 때문에 이런 표현을 할 수 없다.기본형의 한계를 이해하기 위해, 두 값을 비교해서 다음과 같은 결과를 출력하는 간단한 코드를 작성해보자.
-101package 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); //숫자를 문자로 변경
}
}
MyInteger 는 int value 라는 단순한 기본형 변수를 하나 가지고 있다.compareTo() 메서드를 클래스 내부로 캡슐화 했다.MyInteger 클래스는 단순한 데이터 조각인 int 를 내부에 품고, 메서드를 통해 다양한 기능을 추가했다. 덕분에 데이터 조각에 불과한 int 를 MyInteger 를 통해 객체로 다룰 수 있게 되었다.
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 는 기본형이기 때문에 스스로 메서드를 가질 수 없다.기본형은 항상 값을 가져야 한다. 하지만 때로는 데이터가 '없음'이라는 상태가 필요할 수 있다.
다음 코드를 작성해보자.
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 이 발생할 수 있기 때문에 주의해서 사용해야 한다.