제네릭(generic)은 개발자가 의도한 타입만 저장할 수 있도록 하는 것으로 데이터의 타입을 강제하는 것입니다.
즉, 타입을 일반화한다(generalize)는 것을 의미합니다.
제네릭은 메소드나 클래스에서 사용할 내부 데이터 타입을 컴파일 시에 미리 지정하는 방법입니다.
컴파일 시에 미리 타입 검사(type check)를 수행하면 다음과 같은 장점을 가집니다.
1. 클래스나 메소드 내부에서 사용되는 객체의 타입 안정성을 높일 수 있습니다
2. 반환값에 대한 타입 변환 및 타입 검사에 들어가는 노력을 줄일 수 있습니다.
class MyArray<T> {
T element;
void setElement(T element) {
this.element = element;
}
T getElement() {
return element;
}
}
위의 코드에서 보면 T를 타입 변수라고 합니다.
이 타입 변수는 임의의 참조형 타입입니다.
꼭 T가 아니더라도 다른 문자를 사용해도 상관은 없지만 Type의 첫 글자를 따와서 T라고 지정해 주었습니다.
이런 임의의 참조형 타입 변수로 주로 사용하는 알파벳이 있습니다.
T - Type ( ? : wild card (알 수 없는 타입) )
E - Element
K - Key
N - Number
V - Value
이외 제네릭 타입은 일반적으로 대문자의 알파벳 한문자로 표현합니다.
또한 여러 개의 타입 변수는 , 를 통해 구분하여 명시할 수 있습니다.
이러한 타입 변수는 클래스뿐만 아니라 메소드의 매개변수나 리턴 값으로도 사용할 수 있습니다.
하지만 개발 코드에서는 타입 변수 자리에 구체적인 타입을 지정해야 합니다.
마찬가지로 제네릭 클래스(generic class)를 생성할 때에는 타입 변수 자리에 사용할 실제 타입을 명시해야 합니다.
MyArray<Integer> myArr = new MyArray<Integer>();
이와 같이 임의의 참조형 타입을 넣는 것이 아닌 사용할 실제 타입을 기입해야 합니다.
List list = new ArrayList();
list.add("hello");
String str = (String)list.get(0);
List<String> list = new ArrayList<String>();
list.add("hello");
String str = list.get(0);
이와 같이 add라는 메소드를 사용해서 "hello"라는 문자를 입력할 때 우리는 당연히 String 타입이라고 생각하지만 자바는 Object 타입으로 인식을 합니다.
따라서 제네릭이 없을 경우 묵시적 형 변환이 이루어지고 이후 호출할 때 명시적 형 변환이 없다면 에러가 발생합니다.
하지만 제네릭으로 String 타입을 강제한다면 Object 타입이 아닌 String 타입으로 인식하여 형 변환이 없어도 에러가 발생하지 않습니다.
Emp.java
package com.generic;
public class Emp<T> {
private T empno;
private String ename;
public Emp() {
}
public Emp(T empno, String ename) {
this.empno = empno;
this.ename = ename;
}
public T getEmpno() {
return empno;
}
public void setEmpno(T empno) {
this.empno = empno;
}
public String getEname() {
return ename;
}
public void setEname(String ename) {
this.ename = ename;
}
}
MTest.java
package com.generic;
public class MTest {
public static void main(String[] args) {
Emp emp = new Emp();
emp.setEmpno(111);
emp.setEname("홍길동");
System.out.println(emp.getEname() + ":" + emp.getEmpno());
Emp emp2 = new Emp("112a", "김선달");
System.out.println(emp2.getEname() + ":" + emp2.getEmpno());
Emp<String> emp3 = new Emp<String>("123a", "이순신");
System.out.println(emp3.getEname() + ":" + emp3.getEmpno());
Emp<Integer> emp4 = new Emp<Integer>(11, "킹세종");
System.out.println(emp4.getEname() + ":" + emp4.getEmpno());
}
}
'Java 관련 > Java' 카테고리의 다른 글
[Java] 백터(Vector) & 향상된 for문(foreach) (0) | 2021.11.12 |
---|---|
[Java] 컬렉션(Collection framework) (0) | 2021.11.11 |
[Java] 싱글톤 패턴(Singleton pattern) (0) | 2021.11.09 |
[Java] 내부 클래스(inner class) (0) | 2021.11.08 |
[Java] 인터페이스(interface)를 이용한 도형의 넓이 구하기 & 캡슐화 (0) | 2021.11.07 |