[java] 제네릭(generic)이란?

728x90
반응형

 

제네릭이란?

인스턴스화 시에 다룰 데이터 타입을 확정

다양한 타입의 객체들을 다루는 메서드나 클래스에 컴파일 시의 타입 체크를 해주는 기능

다룰 객체의 타입을 미리 명시하여 객체의 형 변환 불필요

List<참조타입> test = new ArrayList<참조타입>(); // 위와 같은 지정된 참조타입으로만 데이터 저장과 호출 가능

 

제네릭 장점

타입의 안정성

형 변환 작업 불필요

코드 간결 – 형 변환 불필요로 인한 형 변환 코드 없음

 

제네릭 와일드카드

자바 클래스의 메서드의 매개변수 타입을 받을때 사용

슈퍼클래스가 참조타입으로 올 수 있는 형태로 제네릭도 사용가능

클래스, 인페이스도 활용 가능

public void test(List<? extends 슈퍼클래스> test ){}

슈퍼클래스 참조타입으로 슈퍼클래스 상속받은 서브클래스 전체 대입가능

public void test(List<? super 서브클래스> test){} // 해당 서브 클래스 참조타입으로 해당 서브클래스와 슈퍼클래스 대입가능

 

 


참조타입부분 명시와 객체화 대상에도 명시

List<String> list = new ArrayList<String>();

기본타입 명시 불가

그렇다면 기본타입 명시는?

-> 래퍼클래스로 명시한다.

 

List<Integer> intList = new ArrayList<Integer>();
List<Double> doubleList = new ArrayList<Double>();

확정된 타입만 대입 및 데이터를 가져올 수 있다.

 

(X) intList.add("");

(X) String str = intList.get(1);

제네릭이 명시가 안되어있다면 object로 간주한다.

 

List objList = new ArrayList();

이는 데이터를 꺼내올 때 문제가 발생한다.

명시가 안된 데이터는 object임으로 캐스팅이 필요하다.

 

String name = (String) objList.get(0);

제네릭이 명시가 안되어 있을 경우 어떠한 데이터가 삽입되어있는지 모른다. 즉, 타입 확인 연산자를 활용하여 확인해야하며, 이러한 작업으로 인해 작업할 코드의 길이가 길어진다.

일일히 instanceof로 타입을 확인해야한다.

슈퍼, 서브 클래스 확인도 가능

 

if (objList.get(1) instanceof Integer) {
    System.out.println("숫자입니다.");
    int num = (int) objList.get(1);
    System.out.println("숫자확인 " + num);	
}

 


직접 만들 일은 없지만 내부 구성이 어떻게 되어있는지 알아보자

제네릭 기본 변수 표기

T => type(자료형)

E => Element(배열 혹은 집합)

K => key

V => value

 

package kr.or.generic;
/***
 * 제네릭 기본 변수 표기
 * T => type(자료형)
 * E => Element(배열 혹은 집합)
 * K => key
 * V => value 
 * */

interface MyIn <T>{
	public void setTypeName(T typeName);
	public T getTypeName();
}

class SuperMyClass <T> implements MyIn <T>{
	/* 명시된 기호(변수) 멤버 구성하기 */
	//기호로 명시된 멤버는 객체화시 확정
	//필드
	private T typeName;
	//메서드
	public void setTypeName(T typeName) {
		this.typeName = typeName;
	}
	public T getTypeName() {
		return typeName;
	}
}

class MyClass <T> extends SuperMyClass <T>{
	/* 명시된 기호(변수) 멤버 구성하기 */
	private T subTypeName;

	public T getSubTypeName() {
		return subTypeName;
	}

	public void setSubTypeName(T subTypeName) {
		this.subTypeName = subTypeName;
	}	
	
}
/*
 * <> 안에 들어간거 갯수 무한대. 확정적인 타입을 받겠느냐 임의적으로 쓸 수 있다. 대부분 하나에서 두세개정도 해서 클래스를 선언하기도 한다.여러개의 제네릭을 활용해서 타입을 받을 수 있다.
 * */
class MyKeyValue <K,V>{
	
}

public class Javabasic02 {

	public static void main(String[] args) {
		
		SuperMyClass<String> my = new MyClass<String>();
		my.setTypeName("홍길동");
		System.out.println(my.getTypeName());
		
		//인터페이스 		       클래스
		MyIn<String> my2 = new MyClass<String>();
		
		MyKeyValue<String, Object> kv = new MyKeyValue<String, Object>();
	}

}

 


 

와일드카드 활용

 

package kr.or.generic;

import java.util.ArrayList;
import java.util.List;

class SuperClass{
}

class SubClass extends SuperClass{
}

class MyGeneric<T>{
}

class My{
	/*****************
	 * <? super T>
	 * T 슈퍼 클래스와 참조타입으로 객체화 된 서브클래스와 슈퍼 클래스
	 * <? extends T>
	 * T 슈퍼클래스를 상속받은 서브클래스
	 */
	
	/*
	 * 제네릭 와일드 카드 활용
	 * 해당 메서드는 SuperClass 슈퍼 클래스 및
	 * SuperClass를 상속받은 클래스를 담은 List를
	 * 인자로 받는다.
	 * */
	public void setClass(List<? super SuperClass> myClass) {		
	}
	/*
	 * 명시된 타입을 상속받은 대상만 인자값으로 받을 수 있다.
	 * 해당 메서드의 인자로 들어오는 대상들은
	 * SuperClass를 상속받은 대상만 객체화하여
	 * 인수로 삽입이 가능하다.
	 * */
	public void setClass2(List<? extends SuperClass> myClass) {		
	}
	/*
	 * 명시된 타입을 상속받은 대상만 인자값으로 받을 수 있다.
	 * */
	public void setClass3(MyGeneric<? extends SuperClass> myClass) {	
	}
}

public class Javabasic03 {

	public static void main(String[] args) {
		/*와일드 카드*/
		//? -> 전체
		List<?> list = null;
		list = new ArrayList<String>();
		list = new ArrayList<Integer>();
		
		/**
		 * 제네릭을 활용한 참조 타입 부분에서는
		 * 와일드 카드 활용이 가능하다.
		 * 객체화 대상에서는 와일드 카드 사용 불가능
		 * 참조타입 앞부분 가능, 뒷쪽은 불가능
		 * */		
		List<SuperClass> list5 = new ArrayList<SuperClass>();
		list5.add(new SubClass());
		
		List<SuperClass> list7 = new ArrayList<SuperClass>();
		list5.add(new SubClass());

		My my = new My();
		my.setClass(list5);
		//슈퍼클래스 참조타입으로만 받도록 명시되어있음으로 서브클래스
		//타입으로 확정하여 인수를 삽입할 수 없다.
		//my.setClass(list7);
		
		List<SubClass> list3 = new ArrayList<SubClass>();
		list3.add(new SubClass());
		my.setClass2(list3);
		
		MyGeneric<SubClass> mg = new MyGeneric<SubClass>();
		my.setClass3(mg);		
	}
}
728x90
반응형