Java
소스 레벨에서 데이터 타입이 결정되지 않고, 별칭(타입파라미터)만 지정한다.
객체 생성싯점, 구현클래스 구현싯점, 메소드 실행싯점에 별칭을 대신할 데이터 타입을 외부에서 지정하는 것이다.
제네릭은 <> 다이아몬드 표기법으로 타입파라미터(별칭)를 지정한다.
배열처럼 다양한 타입의 객체를 다루는 클래스를 설계할 때 사용한다.
자바에서는 객체를 여러개 저장하는 콜렉션 클래스들이 대표적인 예다.
사용 목적
사용 예
ArrayList<Product> products = new ArrayList<Product>();
ArrayList<Order> orders = new ArrayList<Order>();
ArrayList<Book> books = new ArrayList<Book>();
HashSet<Team> teams = new HashSet<Team>();
package generic;
public class BoxApp {
public static void main(String[] args) {
// 문자열을 저장하는 NormalBox와 GenericBox 만들기
// 박스 객체 생성하기
// NormalBox객체에는 어떤 객체가 저장될 예정인지 정보가 전혀 없음
// GenerixBox객체에는 어떤 객체가 저장될것인지 미리 알 수 있음
NormalBox box1 = new NormalBox();
GenericBox<String> box2 = new GenericBox<String>();
box1.setItem("홍길동님 안녕하세요, 오래간만입니다.");
// box1.setItem(new BoxApp()); // 오류 확인 안됨, 원래의 의도와는 다른 객체를 저장해도 에러가 발생되지 않음
// box1.setItem(100); // 오류 확인 안됨, 원래의 의도와는 다른 객체를 저장해도 에러가 발생되지 않음
String text1 = (String) box1.getItem();
System.out.println("### 첫번째 박스의 내용 출력");
System.out.println("메세지 : " + text1);
System.out.println("글자수 : " + text1.length() + " 글자");
box2.setItem("김유신님 잘 지내고 계신가요? 서울로 한번 오세요.");
// box2.setItem(new BoxApp()); // 오류 발생, String객체 외의 다른 객체는 절대로 저장되지 않음
// box2.setItem(100); // 오류 발생, String객체 외의 다른 객체는 절대로 저장되지 않음
String text = box2.getItem();
System.out.println("### 두번째 박스의 내용 출력");
System.out.println("메세지 : " + text);
System.out.println("글자수 : " + text.length() + " 글자");
}
}
package generic;
public class GenericBox<T> {
private T item;
public T getItem() {
return item;
}
public void setItem(T item) {
this.item = item;
}
}
package generic;
/*
* 제네릭이 적용되어 있지 않는 박스 설계도
* 1. 타입안전성이 좋지 않다.
* 2. 저장된 객체가 Object로 형변환 되어서 저장 된다.
* (실제로 저장된 객체를 참조하는 것이 아니라, 저장된 객체의 Object객체를 참조한다.)
* 3. 저장된 객체를 꺼낼때 마다 실제 저장된 타입으로 형변환해야 한다.
*/
public class NormalBox {
private Object item;
public Object getItem() {
return item;
}
public void setItem(Object item) {
this.item = item;
}
}
Set<E>
중복을 허용하지 않는다.(동일한 객체를 2개 저장할 수 없다.
주요 구현 클래스
Set의 구현객체 생성하기
// String 객체를 여러 개 저장하는 HashSet객체 생성하기
Set<String> set1 = new HashSet<String>();
// 정수를 여러 개 저장하는 HashSet객체 생성하기
Set<Integer> set2 = new HashSet<Integer>();
// Book객체를 여러 개 저장하는 HashSet객체 생성하기
Set<Book> set3 = new HashSet<Book>();
// Account객체를 여러 개 저장하는 HashSet객체 생성하기
Set<Account> set4 = new HashSet<Account>();
HashSet<E> 활용하기
public static void main(String[] args) {
// String객체를 여러 개 저장하는 HashSet객체 생성하기
Set<String> set = new HashSet<String>();
// HashSet에 객체 저장하기
set.add("홍길동");
set.add("김유신");
set.add("이순신");
set.add("강감찬");
set.add("류관순");
set.add("강감찬"); // 동일한 객체가 저장되어 있기 때문에 저장되지 않음
// HashSet에 저장된 객체의 갯수 조회하기
int count = set.size();
System.out.println("저장된 객체의 갯수: " + count); // 5가 출력됨
// HashSet이 지정된 객체를 포함하고 있는지 조회하기
boolean hasElement = set.contains("김유신");
System.out.println("김유신을 포함하고 있는가?" + hasElement); // true가 출력됨
// HashSet에서 지정된 객체를 삭제하기
set.remove("홍길동");
// HashSet이 비어있는지 조회하기
boolean empty = set.isEmpty);
System.out.println("비어있는가?" + empty); // false가 출력됨
// HashSet에 저장된 객체를 향상된 for문을 사용해서 순회하기
for (String name : set) {
System.out.println("저장된 이름: " + name);
}
// HashSet에 저장된 모든 객체 삭제하기
set.clear();
}
List<E>
// String객체를 여러 개 저장하는 ArrayList객체 생성하기
List<String> list1 = new ArrayList<String>();
// 실수를 여러 개 저장하는 ArrayList객체 생성하기
List<Double> list2 = new ArrayList<Double>();
// Person객체를 여러 개 저장하는 ArrayList객체 생성하기
List<Person> list3 = new ArrayList<Person>();
public class Person {
private int no;
private String name;
public Person() {}
public Person(int no, String) {
this.no = no;
this.name = name;
}
public int getNo() {
return no;
}
public String name() {
return name;
}
}
public static void main(String[] args) {
// Person객체를 여러 개 저장할 수 있는 ArrayList객체 생
List<Person> personList = new ArrayList<Person>();
// ArrayList객체에 Person객체생성하기
personList.add(new Person(100, "김유신"));
personList.add(new Person(200, "강감찬"));
personList.add(new Person(300, "이순신"));
personList.add(new Person(400, "류관순"));
// ArrayList객체에 저장된 Person객체의 갯수를 조회하기
int count = personList.size();
System.out.println("저장된 갯수: " + count); // 4가 출력됨
// 향상된 for문을 사용해서 ArrayList객체에 저장된 Person객체를 순회하기
for (Person person : personList) {
int no = person.getNo();
String name = person.getName();
System.out.println("번호:" + no + ", 이름:" + name);
}
// ArrayList객체에서 0번에 저장된 Person객체 조회하기
Person person0 = personList.get(0);
// ArrayList객체에서 2번에 칸에 저장된 Person객체 삭제하기
personList.remove(2)
// ArrayList객체에서 1번에 저장된 객체를 새로운 Person객체로 변경하기
personList.set(1, new Person(500, "안중근"));
// ArrayList객체에 저장된 모든 객체 삭제하기
personList.clear()
}
public static void main(String[] args) {
Stack<String> stack = new Stack<String>();
// Stack객체에 문자열 저장하기
stack.push("김유신");
stack.push("강감찬");
stack.push("이순신");
// Stack객체에서 맨 위에 있는 객체를 조회한다.
String value1 = stack.peek(); // 이순신
String value2 = stack.peek(); // 이순신
String value3 = stack.peek(); // 이순신
// Stack객체에서 맨 위에 있는 객체를 꺼낸다.(Stack에서 해당 객체는 삭제된다.)
String value1 = stack.pop(); // 이순신
String value2 = stack.pop(); // 강감찬
String value3 = stack.pop(); // 김유신
// Stack객체가 비어있는지 확인하기
boolean result = stack.isEmpty(); // true가 반환된다.
}
구분 | 배열 | 콜렉션 |
---|---|---|
데이터 | 기본자료형, 객체 | 객체 |
길이 | 불변 | 가변적 |
저장 | 인덱스필요 | 맨 마지막요소의 끝에 자동으로 저장 |
삭제 | 인덱스필요 | 삭제 후 다음요소로 해당 위치가 |
삭제 | 해당부분 데이터가 비어있음 | 자동으로 채워짐 |
Enhanced-for | 배열의 끝까지 반복 | 요소가 있는 부분까지만 반복 |