JAVA
C++ 프로그래머 Java 맛보기 #26
aucd29
2013. 9. 26. 21:07
이번에는 제네릭에 관해서 이야기 하겠다.
제네릭은 c++ 에 템플릿과 비슷한 개념을 가지며 이용법도 비슷하다. 굳이 코딩을 할 때 제네릭을 사용하지 않더라도 큰 문제는 없지만 제너릭을 사용하게 되면 좀더 다형성이 보장되는 코드를 생성할 수 있기 때문에 이용한다.
예를 들어
public class Box {
private Object object;
public void add(Object object) {
this.object = object;
}
public Object get() {
return object;
}
}
라는 베이스 클래스가 존재하고 이를 아래와 같이 사용할 수 있다. Integer 은 Object 를 상속받아 생성한 클래스 이므로 Object 형태를 인지하고 BoxDemo1 은 잘 동작하게 된다. 하지만.
public class BoxDemo1 {
public static void main(String[] args) {
// ONLY place Integer objects into this box!
Box integerBox = new Box();
integerBox.add(new Integer(10));
Integer someInteger = (Integer)integerBox.get();
System.out.println(someInteger);
}
}
아래와 같이 실수로 integerBox.add("10"); 를 입력했을 경우 String 역시 Object 를 상속받았기 때문에 이상 없이 빌드 되버리는 사태가 발생되버리게 된다.
public class BoxDemo2 {
public static void main(String[] args) {
// ONLY place Integer objects into this box!
Box integerBox = new Box();
// Imagine this is one part of a large application
// modified by one programmer.
integerBox.add("10"); // note how the type is now String
// ... and this is another, perhaps written
// by a different programmer
Integer someInteger = (Integer)integerBox.get();
System.out.println(someInteger);
}
}
빌드가 되었으므로 프로그래머는 므흣한 표정으로 실행을 하겠지만.. 오류가 발생하게 된다..
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
at hellojava.Main.useBox2(Main.java:177)
at hellojava.Main.main(Main.java:187)
Java Result: 1
이런......
자 모두 Object를 상속받아서 생긴 모호성 때문에 발생한 문제이므로 명확하게 하기 위해서 제네릭을 이용해 Box 베이스 클래스를 다음과 같이 변경했다
/**
* Generic version of the Box class.
*/
public class Box<T> {
private T t; // T stands for "Type"
public void add(T t) {
this.t = t;
}
public T get() {
return t;
}
}
T에 직접 사용할 타입을 정의해주면 되는데
Box<Integer> integerBox;
예제를 만들어보면 다음과 같다. 타입을 정해 두었기 때문에 항상 지정된 타입으로 인스턴스 해야 하고 데이터를 가져올 때는 지정된 값으로 리턴하기 때문에 캐스팅이 필요가 없다.
public class BoxDemo3 {
public static void main(String[] args) {
Box<Integer> integerBox = new Box<Integer>();
integerBox.add(new Integer(10));
Integer someInteger = integerBox.get(); // no cast!
System.out.println(someInteger);
}
}
그리고 문제가 되었던 integerBox.add("10"); 와 같은 코드를 입력하게 되면 빌드시 경고 메시지를 볼 수가 있다.
제네릭에서는 타입 파라메터에 대한 규칙이 존재하는데 다음과 같다.
E - Element
K - Key
N - Number
T - Type
V - Value
S, U, V - 2nd, 3rd, 4th type
제네릭은 c++ 에 템플릿과 비슷한 개념을 가지며 이용법도 비슷하다. 굳이 코딩을 할 때 제네릭을 사용하지 않더라도 큰 문제는 없지만 제너릭을 사용하게 되면 좀더 다형성이 보장되는 코드를 생성할 수 있기 때문에 이용한다.
예를 들어
public class Box {
private Object object;
public void add(Object object) {
this.object = object;
}
public Object get() {
return object;
}
}
라는 베이스 클래스가 존재하고 이를 아래와 같이 사용할 수 있다. Integer 은 Object 를 상속받아 생성한 클래스 이므로 Object 형태를 인지하고 BoxDemo1 은 잘 동작하게 된다. 하지만.
public class BoxDemo1 {
public static void main(String[] args) {
// ONLY place Integer objects into this box!
Box integerBox = new Box();
integerBox.add(new Integer(10));
Integer someInteger = (Integer)integerBox.get();
System.out.println(someInteger);
}
}
아래와 같이 실수로 integerBox.add("10"); 를 입력했을 경우 String 역시 Object 를 상속받았기 때문에 이상 없이 빌드 되버리는 사태가 발생되버리게 된다.
public class BoxDemo2 {
public static void main(String[] args) {
// ONLY place Integer objects into this box!
Box integerBox = new Box();
// Imagine this is one part of a large application
// modified by one programmer.
integerBox.add("10"); // note how the type is now String
// ... and this is another, perhaps written
// by a different programmer
Integer someInteger = (Integer)integerBox.get();
System.out.println(someInteger);
}
}
빌드가 되었으므로 프로그래머는 므흣한 표정으로 실행을 하겠지만.. 오류가 발생하게 된다..
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
at hellojava.Main.useBox2(Main.java:177)
at hellojava.Main.main(Main.java:187)
Java Result: 1
이런......
자 모두 Object를 상속받아서 생긴 모호성 때문에 발생한 문제이므로 명확하게 하기 위해서 제네릭을 이용해 Box 베이스 클래스를 다음과 같이 변경했다
/**
* Generic version of the Box class.
*/
public class Box<T> {
private T t; // T stands for "Type"
public void add(T t) {
this.t = t;
}
public T get() {
return t;
}
}
T에 직접 사용할 타입을 정의해주면 되는데
Box<Integer> integerBox;
예제를 만들어보면 다음과 같다. 타입을 정해 두었기 때문에 항상 지정된 타입으로 인스턴스 해야 하고 데이터를 가져올 때는 지정된 값으로 리턴하기 때문에 캐스팅이 필요가 없다.
public class BoxDemo3 {
public static void main(String[] args) {
Box<Integer> integerBox = new Box<Integer>();
integerBox.add(new Integer(10));
Integer someInteger = integerBox.get(); // no cast!
System.out.println(someInteger);
}
}
그리고 문제가 되었던 integerBox.add("10"); 와 같은 코드를 입력하게 되면 빌드시 경고 메시지를 볼 수가 있다.
제네릭에서는 타입 파라메터에 대한 규칙이 존재하는데 다음과 같다.
E - Element
K - Key
N - Number
T - Type
V - Value
S, U, V - 2nd, 3rd, 4th type