본문 바로가기

study/java

자바/JAVA 제네릭

생활코딩 강의를 듣고 적는 글입니다.

 

제네릭(Generic)은 클래스 내부에서 사용할 데이터 타입을 외부에서 정하는 기법이다. 

 

 클래스를 선언할 때, 클래스 이름 뒤에 다이아몬드 꺽쇠 안에 데이터 타입 변수를 선언한다. 보통 T라고 한다. 이 T는 정해지지 않은 데이터 타입이다. 그리고 이 클래스로 객체를 만들 때, T의 구체적인 타입을 정할 수 있다.(복수로 사용할 수 도 있다.) 다음과 같이 사용할 수 있다.

 p1을 생성할 때는 꺽쇠 안에 String을 넣었다. 그러면 p1.info의 타입은 String이 된다. 마찬가지로 p2.info의 타입은 StringBuilder가 된다.

class Person<T> {
	public T info;
}
Person<String> p1 = new Person<String>();
Person<StringBuilder> p2 = new Person<StringBuilder>();

 

 그러면 왜 제네릭을 사용할까? 자바에선 변수를 선언할 때, 데이터 타입을 이용해 자신이 원하는 데이터 타입만 담을 수 있는 변수를 만들 수 있다. 따라서 원하지 않는 데이터는 들어올 수 없다.

 

 어떤 메서드들이 있다고 하자. 이 메서드들은 중복되는 코드가 많아 하나의 메서드로 만들려고 하는데, 사용되는 데이터 타입이 달라 어쩔 수 없이 Object 타입으로 업 캐스팅하여 데이터를 받는다. 하지만 그렇게 되면 원하지 않는 데이터 타입도 받을 수 있게 된다. 타입 안정성을 보장받지 못한다. 하지만 제네릭을 이용하면 타입 안정성을 보장 받을 수 있다.

 

제네릭에서 받는 타입 파라미터의 데이터 타입은 레퍼런스타입만 들어올 수 있다. Object 타입은 기본값이 아니라 객체를 상속받기 때문이다. 좀 더 자세한 내용은 밑 링크에 있다.

jang-sn.tistory.com/28

 

제네릭은 생략이 가능하다. 만약 A,B타입을 타입 매개변수로 갖는 클래스가 있고 그 클래스의 객체를 생성할 때, 생성자의 매개변수로 A 타입의 a , B 타입의 b를 전달하면 제네릭을 명시하지 않아도 된다.

A a;
B b;

Exam<A,B> exam = new Exam<A,B>(a,b);
//
//이럴 땐 제네릭을 생략할 수 있다.
//
Exam exam = new Exam(a,b);//결과는 같다

 

제네릭은 메소드에도 적용할 수 있다. 메서드의 매개변수에 제네릭을 적용할 수 있다.

public <U> void print(U res){
	Sytem.out.println(res);
 }
 
 String str = "hello";
 
 xxxx.<String>print(str);// hello

 

 

제네릭은 원하는 타입만 받을 수 있다. extends 키워드를 이용하면 된다. class Exam<T extends person>이라고 한다면 person 클래스의 객체 거나 또는 person의 자식 클래스만 들어올 수 있다. 여기서 person은 클래스가 아니어도 된다. 인터페이스여도 그 인터페이스를 구현하는 객체를 넣어 제네릭을 이용할 수 있다. 그럴 때도 extends라는 키워드를 사용한다.