728x90

이 강의는 자바의 프로젝트를 어떻게 만드는지, 또한 빌드를 어떻게 하는지에 대한 강의를 진행하지 않는다.

그러나 자바의 기본적인, 그리고 자바에 필수적인 기능들도 분명 존재하고 이 블로그엔 그 작업에 필요한 포스팅도 함께 제공하고 있다.

그 정보를 확인하고 싶다면 여기를 참조하라. 양이 조금 되고 현재진행형으로 늘어나고 있으므로 페이지내의 찾기(ctrl+f 나 cmd+f)로 찾아보도록하자.


저번에 이어서 이번에도 java.lang패키지의 일부를 다루려고한다.

이번에 다룰 것은 바로 래퍼클래스이다.

래퍼 클래스는 뭐 사실 어렵지도 않고 대단치도 않다.

래퍼 클래스는 우리가 쓰는 기본타입(Primitive Type:프리미티브 타입)을 클래스화 시켜둔거라고 생각하면 편하다.

일단 먼저 예제부터 보도록하자.


package com.jiharu.main;

public class Main {

public static void main(String[] args) {
int num1 = 10;
Integer num2 = 20;

float f1 = 3.14f;
Float f2 = 2.17f;

char c1 = 'A';
Character c2 = 'a';

double d1 = 1.1;
Double d2 = 2.2 ;
}
}

자바에 존재하는 모든 primitive type들은 클래스로 래핑한 Wrapper클래스가 존재한다.

이 클래스들은 사실 쓰는게 일반 기본타입들과 똑같이 쓴다.

사실상 거의 차이없게 쓰는 수준이다.

덧셈과 뺄셈, 그리고 연산등을 똑같이 쓸 수 있다.

과거 JDK1.4까지는 그렇지는 않았는데 JDK1.5로 넘어오면서 똑같이 쓸 수있게 바뀌었다.

Wrapper Class는 기본 타입을 클래스화 시켰으므로 메모리를 더 잡아먹으면서 기본타입과 똑같은 기능을 한다.


이 까지 보면 아무 쓸모 없어보인다.

기본 연산과 똑같이 할 수 있으면서 메모리는 더먹는데 도대체 왜쓰는가?

필자가 생각하기에 Wrapper Class를 사용하는 이유는 크게 보면 3가지이다.


첫번째는 바로 Generic이 사용가능하다는 것이다.

아직 배운 개념은 아니지만 Generic은 인자로 클래스만 사용가능하다.

그러나 프리미티브타입은 클래스가 아니므로 넣을 수 없다.

이때는 Wrapper Class말고 다른 경우의 수는 아예 없다고 할 수 있다.


두번째는 Wrapper Class가 가지고있는 메소드와 필드를 사용하기 위해서이다.

가령 여러분은 int형이 가진 가장 큰 값이 얼마인지 계산하면 알겠지만 이미 Integer클래스에 필드로 정의되어있다.

또한 여러분은 특정 문자열을 parseInt따위의 메소드를 이용해서 값을 바꿀것이다.

아래의 예제를 보자.

package com.jiharu.main;

public class Main {

public static void main(String[] args) {
int num = Integer.parseInt("1234");
System.out.println(num);
System.out.println(Integer.MAX_VALUE);
System.out.println(Integer.MIN_VALUE);
}
}

아마 자주보게될 예제코드일 것이다.

시행결과는 아래와 같다.


Integer클래스들의 메소드를 이용할 수있다. 그런데 보통  사용하는 메소드는 위 정도가 전부다.


세번째는 null상태를 가진다는 것이다.

이는 java가 가진 가능한 축복이자 래퍼클래스를 쓰는 이유이기도 하다.

아래의 예제를 보자.

package com.jiharu.main;

import java.util.Scanner;

public class Main {
static Scanner sc = new Scanner(System.in);

public static void main(String[] args) {
int num;
if (sc.next().equals("yes")) {
num = sc.nextInt();
} else {
num = Integer.MAX_VALUE; //혹은 Integer.MIN_VALUE
}

if (num == Integer.MAX_VALUE) {
System.out.println("숫자를 입력받지 않았습니다.");
} else {
System.out.println("입력받은 숫자는 " + num + "입니다.");
}
}
}

이 예제의 경우는 보통 C스타일의 예제이다.

일반 타입은 null을 가질 수 없으므로 가장 큰값, 혹은 가장 작은 값중 하나를 안쓴다고 가정한다.

그리고 그 상태를 입력받지 않은 상태라고 가정하는 것이다.

위의 예제는 사용자의 입력이 yes이면 숫자를 입력받고 아니면 숫자를 입력받지 않은 상태를 주는 것이다.

그러나 int는 기본타입으로 숫자밖에 못가지기에 입력받지 않은 상태를 가장 큰값, 혹은 가장 작은 값으로 약속하는 것이다.

그러나 여러분도 아시다시피 이 코드는 잠재적으로 문제를 일이킬 가능성이 매우높다.

입력을 아래와 같이 하면 말이다.



분명 숫자를 입력받았음에도 불구하고 int가 가지는 가장 큰값을 넣었다.

우리는 안쓰자고 약속을 했으나 프로그램이 우리 마음대로 된다는 보장은 없다.

물론 C에서는 이렇게 무조건 써야했으므로 온갖 장치를 달아놔야했다.

그리고 코딩은 더 어렵게 되었다.

만약 Integer클래스를 사용한다면 null이 사용가능하므로 이 문제에서 깔끔하게 해방될 수 있다.


package com.jiharu.main;

import java.util.Scanner;

public class Main {
static Scanner sc = new Scanner(System.in);

public static void main(String[] args) {
Integer num;
if (sc.next().equals("yes")) {
num = sc.nextInt();
} else {
num = null; //혹은 Integer.MIN_VALUE
}

if (num == null) {
System.out.println("숫자를 입력받지 않았습니다.");
} else {
System.out.println("입력받은 숫자는 " + num + "입니다.");
}
}
}

이 예제를 사용해서 다시 테스트를 해보자.



제대로 시행되는걸 확인할 수 있다.

+ Recent posts