JAVA 10강_1_제네릭(generic)_예시1

열라뽕따히·2024년 2월 25일
0

JAVA

목록 보기
61/79
post-thumbnail

제네릭(generic) 이란?

  • 포괄적인, 총괄적인, 일반적인

  • 자바에서 제니릭(generic)이란 데이터의 타입(data type)을 일반화한다(generalize)는 것을 의미
    ==> 즉, 자바에서 제네릭은 클래스 내부에서 사용할 데이터 타입을 외부에서 지정하는 기법을 말함 객체별로 다른 타입의 자료가 저장될 수 있도록 함

  • 모든 종류의 타입을 다룰 수 있도록, 클래스나 메서드를 타입 매개변수(generic type)을 이용하여 선언하는 기법임

  • 특정한 클래스에 원하는 객체 타입을 지정하여 지정된 객체만 저장하게 하는 자바 문법

  • 동일한 프로그램 코드에 다양한 데이터 타입을 적용할 수 있도록 클래스와 메서드들을 일반화시켜 제네릭 메서드와 제네릭 클래스를 만들고, 제네릭 메서드나 제네릭 클래스에 개발자가 원하는 데이터 타입으로 구체화시켜 메서드나 클래스의 프로그램 코드를 틀에서 찍어내는 듯이 생산하는 기법임

  • 다양한 타입의 객체들을 다루는 메서드나 다음에 학습할 컬렉션에서 컴파일 할 때 타입을 확인해 주는 기능
    ==> 즉, 다루어질 객체의 타입을 미리 명시해 줌으로써 번거로운 형변환 작업을 줄여준다는 장점이 있음. 또한 객체의 타입을 컴파일 시에 체크하여 주기 때문에 객체의 타입 안전성을 높여 준다는 장점도 있음.

  • jdk 1.5 버전부터 추가된 기능

  • 데이터의 명확성과 안전성을 보장해줌
    ==> 다른 데이터 타입의 데이터가 들어올 경우, 컴파일 시점에서 error 발생

<E> : Element 를 의미하며 컬렉션에서 요소임을 나타냄
<T> : Type을 의미함
<V> : Value를 의미함
<K> : Key를 의미함





<예시1> : 제네릭 사용 X


Apple 클래스, Pencil 클래스 생성




=============================코드=============================

//////////// Apple 클래스 

public class Apple {
	
	void output() {
		System.out.println("사과입니다!");
	}

}

//////////// Pencil 클래스

public class Pencil {
	
	void output() {
		System.out.println("연필입니다!");
	}

}



Apple 타입의 apple 변수와 Pencil타입의 pencil 변수를 만들 Goods_01, Goods_02클래스 생성




=============================코드=============================

//////////////// Apple변환타입의 apple 변수 생성
public class Goods1 {
	
	private Apple apple;

	public Apple getApple() {
		return apple;
	}

	public void setApple(Apple apple) {
		this.apple = apple;
	}
	
}

//////////////// Pencil변환타입의 pencil 변수 생성
public class Goods2 {
	
	private Pencil pencil;

	public Pencil getPencil() {
		return pencil;
	}

	public void setPencil(Pencil pencil) {
		this.pencil = pencil;
	}

}



Goods1, Goods2 객체를 활용하여 메서드 출력할 Goods_01 클래스 생성




=============================코드=============================

public static void main(String[] args) {
		
		// Goods1 객체를 이용하여 Apple 객체를 추가하거나 가져오기
		
		Goods1 goods1 = new Goods1();
		
		// Apple 객체 타입만 입력이 가능
		//Apple apple = new Apple();
		//goods1.setApple(apple); 
		// 위 두 코드를 합하면 밑에처럼 작성 가능 ↓
		
		goods1.setApple(new Apple());  // Apple 객체 생성
		
		Apple apple = goods1.getApple();
		
		apple.output();
		
		goods1.getApple();
		
		System.out.println();
		
		// Goods2 객체를 이용하여 Pencil 객체를 추가하거나 가져오기
		Goods2 goods2 = new Goods2();
		
		// Pencil 객체 타입만 입력이 가능
		goods2.setPencil(new Pencil());  // Pencil 객체 생성
		
		Pencil pencil = goods2.getPencil();  // pencil 타입으로 호출
		
		pencil.output();
		
	}

=============================실행=============================





위의 방법들을 한번에 처리하는 방법 : Object 활용 방법이 있다!

Goods 클래스 생성



=============================코드=============================

public class Goods {
	
	private Object object;

	
	public Object getObject() {
		return object;
	}

	public void setObject(Object object) {
		this.object = object;
	}
	
}

메인메서드로 출력할 Goods_02 클래스 생성




=============================코드=============================

public static void main(String[] args) {
		
		Goods goods = new Goods();
		
		goods.setObject(new Apple());
		
		Apple apple = (Apple)goods.getObject(); // apple이 Apple의 타입이기 때문에 형변환이 필요!
		                                        // getObject는 Object타입임
		
		apple.output();
		
		System.out.println();
		
		////////////////////////////////////////
		
		Goods goods1 = new Goods();
		
		goods1.setObject(new Pencil());
		
		Pencil pencil = (Pencil)goods1.getObject(); // 
		                                            
		
		pencil.output();
		
		System.out.println();

=============================실행=============================





위의 예시를 통해 알 수 있는 것


데이터를 저장할 때는 상관이 없지만, 저장된 데이터를 각각의 타입(Apple, Pencil)을 꺼내오기 위해서는 저장된 형태로 캐스팅(형변환)을 해야 함.

필드 자체가 Object 타입이기 때문에 get() 메서드를 가져오는 타입 또한 항상 Object 타입이 됨
따라서 Apple 객체를 저장했을 때는 get() 메서드로 가져온 Object 타입을 Apple 타입으로, Pencil 객체를 저장했을 때는 가져온 Object 타입을 Pencil 객체 타입으로 캐스팅을 해주어야 함

정확하게 해당 객체 타입으로 형변환을 해주는 경우에는 문제가 발생하지 않지만, 다른 객체 타입으로 형변환을 해주게 되면 실행 중에 예외(ClassCaseException)가 발생할 수 있음
이렇게 되면 정상적으로 프로그램이 종료되지 않는 문제가 발생할 수 있음

Object 타입으로 선언된 변수에 데이터가 들어가는 경우, 해당 변수에 있는 값을 꺼내고 싶은 경우에는 반드시 형변환 작업이 필요함
이러한 형변환 작업이 자주 일어나게 되면 프로그램 성능이 저하될 수 있음
이 문제점을 해결하는 것이 바로 제네릭(generic)




그렇다면 이제 제네릭을 활용하여 형변환 없이 출력해보자!

Good 클래스 생성


=============================코드=============================
public class Good<T> {  // T는 타입이라는 뜻
	
	private T t;

	public T getT() {
		return t;
	}

	public void setT(T t) {
		this.t = t;
	}
	
}

메인메서드로 출력할 Good_03 클래스 생성




=============================코드=============================

public static void main(String[] args) {
		
		Good<Apple> good1 = new Good<Apple>();  // Apple 객체 타입만 받겠다!
		
		good1.setT(new Apple());
		
		Apple apple = good1.getT();
		
		apple.output();
		
		System.out.println();
		
		///////////////////////////////////////
		
		Good<Pencil> good2 = new Good<>();  // new Good<Pencil>의 Pencil은 생략 가능
		
		good2.setT(new Pencil());
		
		Pencil pencil = good2.getT();
		
		pencil.output();

	}

=============================실행=============================

0개의 댓글