컴파일시 타입을 체크 해주는 기능 (compile-time type check) -jdk1.5
제네릭스 이전
public static void main(String[] args) {
//컬렉션에는 여러가지 자료형을 담을 수 있다. (list,Set,Map)
ArrayList list = new ArrayList();
list.add(new String("12345"));
list.add(new Book());
list.add(new Student());
list.add(new Car());
System.out.println("저장된 객체 수 : " +list.size());
System.out.println("list : "+ list);
//책만 꺼내고 싶어요
for (int i = 0; i < list.size(); i++) {
Object obj = list.get(i);
if(obj instanceof Book) {
System.out.println("책 객체 : " + obj);
}
}
for (int i = 0; i < list.size(); i++) {
Object obj = list.get(i);
if(obj instanceof Book) {
System.out.println("책 객체 : " +obj);
}else if(obj instanceof Car) {
System.out.println("자동차 객체 : " + obj);
}else if (obj instanceof Student) {
System.out.println("학생 객체 : " + obj);
}else if (obj instanceof String) {
System.out.println("일반 문자 : "+ obj);
}
}
}
}
class Book {
private String bNo;
public Book() {}
public Book(String bNo) {
this.bNo = bNo;
}
@Override
public String toString() {
return "나는 " + bNo + "입니다.";
}
}
class Student {
private String stuNo;
public Student() {}
@Override
public String toString() {
return "나는 학생 입니다.";
}
}
class Car {
private String model;
public Car() {}
public Car(String mdel) {
this.model =model;
}
@Override
public String toString() {
return "나는" + model + "입니다1";
}
}
제네릭스 이후
public static void main(String[] args) {
HashMap<String, Book> hmap = new HashMap<>();
inputMap(hmap);
outputMap(hmap);
}
public void method1() {
ArrayList list1 = new ArrayList();
list1.add(new Book());
list1.add(new Car());
// Book만 받기 위한 리스트
ArrayList<Book> list2 = new ArrayList<>();// 뒤는 생략가능
list2.add(new Book());
// list2.add( new Car()); <- 에러
//Book만 받도록 한정지은 컬렉션 객체
for(Book bk : list2) {
// list2안에 Book객체만 들어있기 때문에
// Book 형태로 굳이 형변환 하지 않고도 사용이 가능하다.
System.out.println(bk);
}
// for(Car bk : list2) {
// // list2안에 Book객체만 들어있기 때문에
// // Book 형태로 굳이 형변환 하지 않고도 사용이 가능하다.
// System.out.println(bk);
// }
for(Object obj : list1) {
// list안에 어떠한 자료형이 담겨있을 지 모르기 때문에
// Object형태로 받은 다음 Book객체로 변환이 가능한지
// 확인이 필요하다 (instanceof 연산자가 필요)
if (obj instanceof Book) {
Book bk = (Book)obj;
System.out.println(bk);
}
}
}
public static void inputMap(HashMap<String, Book> hmap) {
//전달받은 HashMap에 객체 저장하기
hmap.put("1", new Book("갈매기의 꿈"));
hmap.put("2", new Book("나의 라임 오렌지나무"));
hmap.put("3", new Book("갈매기의 꿈"));
hmap.put("4", new Book("자바에서 살아남기"));
System.out.println("총 : " +hmap.size() + "권의 책이 저장되었습니다.");
}
public static void outputMap(HashMap<String, Book> hmap) {
// 매개변수로 hashmap을 받아 목록화하여 키의 값을 한개씩 꺼내는 메소드
// 1. keySet() 메소드를 사용하는 방법
Set<String> keys = hmap.keySet();
Iterator<String> iter = keys.iterator();
while(iter.hasNext()) {
String key = iter.next();
System.out.println(key+ " : " + hmap.get(key));
}
}
위의 코드에서 보면 알 수 있듯 제네릭스 이전에는 컬렉션에 자료형을 넣을 때
제한이 없었기 때문에 객체를 꺼내어 사용할 때 incetanceof를 통해 확인 후 사용해야 했다.
하지만 제네릭스의 등장 이후 미리 컬렉션에 저장할 자료형을 한가지로 제한함으로 써
객체를 꺼내어 사용할 떄 객체에 대한 형 변환을 생략해준다!
ArrayList<Tv> list = new ArrayList<Tv>();
ArrayList<Product> list = new ArrayList<Tv>(); //에러
List<Tv> list = new ArrayList<Tv>(); // 다형성 ArrayList가 List를 구현
List<Tv> list = new LinkedList<Tv>(); // 다형성 LinkedList 가 List를 구현
ArrayList<Porduct> list = new ArrayList<Product>();
list.add(new Product());
list.add(new Tv()); // Product의 자손객체 TV
list.add(new Audio()); // Product의 자손객체 Audio
HashMap<String, Student> map = new HashMap<String, Student>();
map.put("자바왕",new Student("자바킹왕",1,1,100,100,100));
System.out.println(map.get("자바왕").name);
>>> 자바킹왕
class Fruit<t extends Fruit>
Fruit 이외의 타입은 들어올 수 없다.
Box<Apple> appleBox = new Box<Apple>();
Box<Grape> appleBox = new Box<Grape>();
class Box<T>{
static T item ; // 에러
static int compare(T t1, T t2){} // 에러
}
class Box<T>{
T[] itemArr; // 가능
T[] toArray(){
T[] tmpArr = new T[itemArr.length]; // 에러
}
}
new 연산자로 생성할 때에는 타입이 확정되어있어야 하기 때문에 불가.
T는 어떤타입이 올지 모른다!
ArrayList<? extends Porduct> list = new ArrayList<Tv>(); // 가능
ArrayList<? extends Porduct> list = new ArrayList<Audio>(); // 가능
ArrayList<Porduct> list = new ArrayList<Tv>(); // 타입 불일치
static <T> void sort(List<T> list, Comparator<? super T> c)
class FruitBox<T>{ // 다름!!
static <T> void sort(List<T> list, Comparator<? super T> c){
...
}
}
FruitBox<Fruit> fruitBox = new FruitBox<Fruit>();
FruitBox<Apple> fruitBox = new FruitBox<Apple>();
System.out.println(Juicer.<Fruit>makeJuice(fruitBox));
System.out.println(Juicer.<Apple>makeJuice(appleBox));
static <T extends Fruit> Jucice makeJuice(FruitBox<T> box){
String temp =""
for (Fruit f :box.getlist()) temp += f+"";
return new Juice(temp)
}