티스토리 뷰
이번에 설명할 내용은 제네릭입니다. 원래 Collection 프레임워크에 대해 쓰려고 했는데 제네릭을 먼저 설명하는 것이 나을 것 같아서 제네릭에 대해 기술하게 되었습니다. 그럼 이 제네릭은 무엇일까요?
일단 네이버에 Generic이라고 검색하면 '포괄적인, 총칭의' 라는 뜻이 나옵니다. 근데, 이 뜻으로 설명하기에는 자바의 제네릭과는 맞지 않는다는 생각이 들었습니다. 그래서 Generic 단어를 클릭하여 더 살펴보니 the generic character라는 '속성'이란 뜻을 가진 숙어가 있었습니다. 이 자바의 제네릭을 설명하기에는 위 숙어가 딱이라는 느낌이 들었습니다. J2SE 5부터 생긴 제네릭은 속성을 뜻한다고 할 수 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12 |
package blog;
import java.util.ArrayList;
import java.util.List; //자바 util에 있는 기능을 불러온다.
public class generic {
public static void main(String[] args) {
List list = new ArrayList();
list.add("hello");
String s = (String) list.get(0);//타입 캐스팅
}
} |
cs |
위 코딩은 J2SE 5가 있기 이전에 ArrayList에서 데이터를 뽑아오고자 할 때 쓰던 방식입니다. ArrayList는 Collection 프레임워크 중의 하나로 다음에 자세히 기술하도록 하겠습니다. 지금은 다만 저런게 있구나라고 생각하시면 될 것 같습니다. 보시면 ArrayList에서 데이터를 뽑아오기 위해 형변환을 해준 것을 알 수 있습니다. 위와 같이 형변환을 해주지 않으면 ArrayList에 들어간 데이터는 object로 반환하기에 에러를 발생시킵니다. 그런데 J2SE 5로 오면서 다음과 같은 방식으로 바뀌게 되었습니다.
1
2
3
4
5
6
7
8
9
10
11
12 |
package blog;
import java.util.ArrayList;
import java.util.List;
public class generic {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("hello");
String s = list.get(0);
}
} |
cs |
제네릭을 통해서 미리 String타입이 들어올 것을 명시하여 ArrayList에서 데이터를 뽑아올 때 자동으로 object 타입이 아닌 String 타입을 반환하도록 되어있습니다. 형변환 자체가 매우 에러를 발생시킬 여지가 많기 때문에 형변환이 없어진 것 만으로도 안정성이 늘어났다고 할 수 있습니다.
제네릭 사용 이유
제네릭 사용 이유는 다음과 같습니다.
1. 타입 안정성 : 제네릭은 단일 타입의 오브젝트만 저장할 수 있게 해줍니다. 따라서, 다른 형태의 오브젝트가 보관되도록 할 수 없게 해줍니다.
2. 타입 캐스팅이 필요하지 않게 해준다 : 위 코딩에 나와 있는 바와 같이 제네릭은 오브젝트에 대한 타입 캐스팅이 필요하지 않게 해줍니다.
3. 컴파일 시에 에러를 확인 가능하게 해준다 : 런타임 하기 이전에 컴파일 시에 에러를 확인 가능하게 해줍니다. 런타임 시에 에러를 발견하는 것은 매우 위험합니다. 이미 내 손을 떠난 상황에서 에러가 발생한 것을 알게 된다는 것 자체가 매우 위험하기 때문입니다. 그런데, 제네릭을 사용하면 컴파일 시에 에러를 확인할 수 있게 됩니다.
위 코딩은 Collection 프레임워크에서의 사용 예이고 그럼 이번에는 클래스 그리고 메소드 제네릭이 가지고 있는 특징인 wildcard에 대해 알아보도록 하겠습니다.
클래스에서의 제네릭
클래스에서 제네릭은 다음과 같은 형태로 사용됩니다.
1
2
3
4
5
6
7
8
9
10
11
12
13 |
package blog;
public class generic {
public static void main(String[] args) {
person<String> p1 = new person<String>();
p1.info = "이영후";
System.out.println(p1.info);
}
}
class person<T> {
public T info;
} |
cs |
클래스에서는 위와 같이 사용되며, String 타입을 명시해줌으로 p1.info는 사용될 때 String 타입으로 반환됩니다. 여기서 T는 Type의 줄임말입니다. generic에서 parameter들을 정의할 때는 일반적으로 다음과 같이 사용됩니다.
1. T = Type
2. E = Element
3. K = Key
4. N = Number
5. V = Value
사실 혼자 보려한다면 마구잡이로 이름을 정해서 진행해도 상관없지만, 개발자가 혼자서 일을 하게 될 일은 거의 없다고 보는지라 위와 같이 정해진 규칙대로 parameter들을 정의하시면 될 것 같습니다.
메소드에서의 제네릭
메소드에서의 제네릭은 다음과 같이 사용됩니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 |
package blog;
public class generic {
public static void main(String[] args) {
Integer[] intArray = {10, 20, 30, 40};
String[] stringArray = {"가", "나", "다", "라"};
printArray(intArray);
printArray(stringArray);
}
public static <E> void printArray(E[] elements) {
for (E element : elements) {
System.out.println(element);
} //메소드에서의 사용 예
}
} |
cs |
배열이 들어올 때 배열을 출력하도록 되어있습니다. 위와 같이 함으로 배열이 아닌 것이 들어왔을 때는 컴파일 에러를 출력하게 되어 안정성을 높이고 있습니다.
제네릭의 Wildcard와 상속
그럼 마지막으로 제네릭에서의 Wildcard와 상속에 대해 알아보도록 하겠습니다. Wildcard란 제네릭을 선언할 때 <?>라고 선언해주는 것을 뜻합니다. ?로 선언함으로 모든 타입의 매개 변수들을 받을 수 있도록 되어있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39 |
package blog;
import java.util.ArrayList;
import java.util.List;
public class generic {
public static void main(String[] args) {
List<rectangle> list1 = new ArrayList<rectangle>();
List<circle> list2 = new ArrayList<circle>();
list1.add(new rectangle());
list2.add(new circle());
list2.add(new circle());
drawShapes(list1);
drawShapes(list2);
}
public static void drawShapes(List<? extends shape> lists) {
for (shape s : lists) {
s.draw();
}
} //와일드카드 사용과 상속 사용
}
abstract class shape {
abstract void draw();
}
class rectangle extends shape {
void draw() {
System.out.println("네모를 그립니다.");
}
}
class circle extends shape {
void draw() {
System.out.println("원을 그립니다.");
}
} |
cs |
위 코딩은 와일드카드 사용과 상속의 이용에 대해 잘 나와있습니다. 와일드카드로 제네릭을 선언함으로 circle이 오든 rantangle이 오든 똑같은 작동을 하도록 되어있습니다. 한 가지 제약으로 걸린 것은 shape를 상속 받는 것으로 shape를 상속 받지 않은 타입이 올 시에는 오류가 나도록 되어있습니다. 와일드카드의 경우 클래스에서는 사용이 불가능하고, 일반적으로 메소드에서도 사용이 불가능하도록 되어 있습니다. 사용 시에는 Collection 프레임워크에서 제네릭 타입 선언 시에만 사용할 수 있도록 되어 있는 것을 확인할 수 있었습니다. 그럼 다음에는 Collection 프레임워크에 대해 알아보도록 하겠습니다.
'IT > Java' 카테고리의 다른 글
Java - SOAP 통신 예제 (0) | 2017.06.17 |
---|---|
Java - Collections Framework(컬렉션 프레임워크) (0) | 2017.03.05 |
Java - enum (0) | 2017.03.05 |
Java - Interface(인터페이스) (0) | 2017.03.05 |
Java - abstarct class(추상 클래스) (0) | 2017.03.05 |
댓글
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday