본문 바로가기
Programming/JAVA(eclipse)

java 12일차_ 02. 제네릭스( generics )

by yoon9i 2024. 3. 25.

2. 제네릭스( generics )
1) 개념
다양한 타입을 다루는 메서드 및 클래스( 컬렉션 )에서
컴파일시점( * )에 타입체크를 해서 예외를 미리 알 수 있도록 지원가능.

2) 장점 2가지
- 저장하는 객체의 타입 안전성 확보 ( 저장하고자 하는 데이터형을 제한 할 수 있다. )
- 형변환 번거로움을 제거할 수 있다.

3) 제네릭스 표현 ( 타입 파라미터라고 부른다. )
<T>: reference Type 의미
<E>: Element 의미
<K,V>: Key, Value 의미

<T,R> : Return type 의미

4) 특징
- <T> 같은 제네릭은 컴파일 시점에 실제 지정된 타입으로 치환됨.
ex)
<T> ---> <String>

- 타입 파라미터는 인스턴스 멤버로 간주한다.
 static 사용불가, 객체생성불가, instanceof 사용불가
- 클래스 및 인터페이스, 메서드 파라미터로 사용 가능.

 

* generics 사용전

package exam21_generics;

import java.util.Date;

// 값을 저장할 수 있는 클래스: 모든 데이터 저장이 가능
class Box {
	
	Object obj;
	
	public void setValue(Object obj) {
		this.obj = obj;
	}
	
	public Object getValue() {
		return obj;
	}
}// end class



public class GenericTest01_사용전 {
	
	public static void main(String[] args) {
		
		// 문자열만 저장
		Box b = new Box();
		b.setValue("Hello");
		b.setValue(100); // 문제1: 잘못된 데이터를 저장시 컴파일 시점이 아닌 런타임 시점(실행시)에 알 수 있다.
		
		String s = (String)b.getValue(); // 문제2: 항상 형변환이 필요하다.
		System.out.println(s+"\t"+s.toUpperCase());
		
		// 날짜만 저장
		Box b2 = new Box();
		b2.setValue(new Date());
		Date d = (Date)b2.getValue();
		System.out.println(d+"\t"+d.getYear());
		
		
	}
}

 

* generics 사용후

package exam21_generics;

import java.util.Date;

// 값을 저장할 수 있는 클래스: 모든 데이터 저장이 가능
class Box2<T> {
	
	T obj;
	
	public void setValue(T obj) {
		this.obj = obj;
	}
	
	public T getValue() {
		return obj;
	}
}// end class



public class GenericTest02_사용후 {
	
	public static void main(String[] args) {
		
		// 문자열만 저장
		Box2<String> x = new Box2<>(); // new 뒤에 오는 제니릭 타입은 생략 가능하다.
		Box2<String> b = new Box2<String>();
		b.setValue("Hello");
//		b.setValue(100); // 문제1 해결: 잘못된 데이터를 저장시 컴파일 시점에 알수 있다.
		
//		String s = (String)b.getValue(); // 문제2: 항상 형변환이 필요하다.
		String s = b.getValue(); // 문제2 해결: 형변환이 붚필요하다.
		
		System.out.println(s+"\t"+s.toUpperCase());
		
		// 날짜만 저장
		Box2<Date> x2 = new Box2<>(); // new 뒤에 오는 제니릭 타입은 생략 가능하다.
		Box2<Date> b2 = new Box2<Date>();
		b2.setValue(new Date());
//		b2.setValue(100); // 문제1 해결: 잘못된 데이터를 저장시 컴파일 시점에 알수 있다.
		
//		Date d = (Date)b2.getValue(); // 문제2: 항상 형변환이 필요하다.
		Date d = b2.getValue(); // 문제2 해결: 형변환이 붚필요하다.
		System.out.println(d+"\t"+d.getYear());
		
		
	}
}




3. 컬렉션 API

1) 데이터 저장 방법
가. 변수

나. 배열
- 크기 변경 불가
- 같은 데이터타입만 저장 가능
- 지원되는 메서드가 없다.
  나중에 추가된 API 가 Arrays 유틸리티 클래스 이다.

다. 컬렉션 API
- 크기 변경 가능
- 저장하는 데이터 타입에 제한이 없다.
- 지원되는 메서드가 많다.
  추가된 API 가 Collections 유틸리티 클래스 이다.

2) 컬렉션 API 종류
Collection<E> (인터페이스) Map<K, V> ( 인터페이스)
          | (상속)         |
       set<E>(인터페이스) List<E>(인터페이스)         | (구현)
   |         |   HashMap<K, V>( * )
   | (구현)         | (구현)
          HashSet<E>( * ) ArrayList<E>( * )


* 데이터 저장 방식에 따른 3가지 종류
가. set 계열 : 저장되는 데이터의 순서가 없음.
     중복저장이 안됨.( 한 번만 저장됨 )

나. list 계열 : 저장되는 데이터의 순서가 있음.
     중복저장이 가능.

다. map 계열: 데이터뿐만 아니라 데이터의 이름(키)
      까지 같이 저장됨.
      ( key / value 쌍으로 저장됨 )
                   저장순서가 없다.
      key 이용해서 value 얻음.

package exam21_generics;

import java.util.ArrayList;

public class GenericTest03_컬렉션 {
	
	public static void main(String[] args) {
		
		// 순서있고 중복가능 컬렉션 사용: List 계열인 ArrayList 클래스를 사용하자.
		// 기본적으로 컬렉션 API 는 모든 데이터가 저장이 가능하다.
		
		// 1. 제네릭없이사용 ( 거의 사용 안됨 )
		ArrayList list = new ArrayList<>();
		list.add(10); // 문제(1)
		list.add("hello"); 
		list.add(3.14); // 문제(1)
		
		Object obj = list.get(0); // >> list 의 0번째는 가져온다
		
		Object obj2 = list.get(1);
		String str = (String)obj2; // 문제(2) 형변환 필요.
		
		Object obj3 = list.get(2); // >> list 의 2번째는 가져온다
		
		// 2. 제네릭으로 사용 ( 저장할 데이터타입을 제한 )
		// 문자열로 저장 제한
		// public class ArrayList<E> implements List<E> {} 
		ArrayList<String> list2 = new ArrayList<>();
		list2.add("a");
		list2.add("a2");
//		list2.add(10); // 문제(1) 해결: 잘못된 데이터를 저장시 컴파일 시점에 알수 있다.
		
		String str2 = list2.get(1); // 문제(2) 해결
	}
}