라이브러리를 사용할 수 있도록, API 문서들을 읽어 이해할 수 있도록 학습하자.
제네릭 Generic
제네릭을 사용하면 컴파일 시점에 타입이 정해지므로, 명시적인 타입 캐스팅이 필요 없고, 잘못된 타입 사용을 컴파일 타임에 방지할 수 있어 런타임 오류를 줄일 수 있습니다.
제네릭 프로그래밍(generic programmning)
- 일반적인 코드를 작성하고 이 코드를 다양한 타입의 객체에 대하여 재사용하는 프로그래밍 기법
- 타입을 파라미터로 가지는 클래스와 인터페이스를 정의함. (일반적으로, 대문자 알파벳 한 문자로 표현)
- 선언 시 , 클래스/인터페이스 이름 뒤에 "< >" 사이에 타입 파라미터 명시
- '컴파일 단계'에서 '잘못된 타입'으로 발생할 수 있는 문제를 파악
- 컴파일 시 강한 타입 체크 가능, 타입명시/타입변환 제거 가능 (구체적타입을....)
public class Box<T>{
private T t;
public T get(){
return t;
}
public void set(T t){
this.t = t;
}
}
Box<String> box = new Box<String>();
멀티타입 파라미터
제네릭타입은 두개 이상의 타입 파라미터도 사용 가능하다.
Product<Tv, String> product = new Product<>();
(콤마로 구분)
제네릭 메소드
매개변수 타입과 리턴 타입으로 타입 파라미터를 갖는 메소드
public <타입파라미터, ...> 리턴타입 메소드명(매개변수..) {..}
public <T> Box boxing (T t) {..}
===> ??? 오버로딩을 줄일 수 있는건가?
제네릭 메소드 호출 방법
리턴타입 변수 = <구체적타입> 매소드명(매개값) .. //명시적으로 구체적 타입 지정
`Box box = boxing(100);`
리턴타입 변수 = 메소드명(매개값); // 매개값보고 구체적타입 추정함
`Box box = boxing(100);`
제한된 타입 파라미터
상속 및 구현 관계를 이용해 타입을 제한할 수 있다.
`public <T extends 상위타입> 리턴타입 메소드(매개변수, ...) {..}`
T는 상위 타입을 제한한다. (상위타입은 클래스 말고, 인터페이스도 가능)
[상위타입]에 들어가는 클래스를 '상속받은' 하위만 리턴타입이 가능하도록 설정하는것.
예:
public static <T extends 동물> T getAnimal(){
자동차 a = new 자동차();
강아지 b = new 강아지();
뱀 c = new 뱀();
방울뱀 d = new 방울벰();
return (T) b;
// return 뒤에 올수있는 것은, T extends 동물, 즉 b c d만 올수있다.
// a는 동물을 상속 받지 않았으므로 불가능. T자리에 동물 못놓으니
}
타입 파라미터를 대체할 구체적인 타입을 명시한다.
같은 상속 트리 or 인터페이스 연결된 경우만 가능
와일드카드 타입 - ?
?:와일드 카드 타입 - 매개변수(인자)에서 허용
타입 파라미터를 대치하는 구체적인 타입
- `제네릭타입<?>` : Unbound Wildcards (제한없음)
모든 클래스/인터페이스 타입이 올 수 있음 - `제네릭타입<? extends 상위타입>` : Upper Bounded Wildcards(상위 클래스 제한)
상위타입이나, 상위타입의 하위타입만 올 수 있다. - `제네릭타입<? super 하위타입>` : Lower Bounded Wildcards(하위 클래스 제한)
하위타입이나 하위타입의 상위 타입만 올 수 있다
예시
public static void printList(List<?> list) {
for (Object obj : list) {
System.out.println(obj);
}
}
// 사용 예:
List<String> strList = List.of("A", "B", "C");
List<Integer> intList = List.of(1, 2, 3);
printList(strList); // OK
printList(intList); // OK
public static void printNumbers(List<? extends Number> list) {
for (Number n : list) {
System.out.println(n.doubleValue());
}
}
// 사용 예:
List<Integer> intList = List.of(1, 2, 3);
List<Double> doubleList = List.of(1.1, 2.2, 3.3);
printNumbers(intList); // OK
printNumbers(doubleList); // OK
// printNumbers(List.of("a", "b")) 는 오류 발생
public static void addNumbers(List<? super Integer> list) {
list.add(1);
list.add(2);
}
// 사용 예:
List<Object> objList = new ArrayList<>();
List<Number> numList = new ArrayList<>();
addNumbers(objList); // OK
addNumbers(numList); // OK
// addNumbers(List<Double>) 은 오류 발생
제네릭타입을 부모클래스로 사용할 경우
타입 파라미터는 자식클래스에도 기술해야함
public class **ChildProduct<T,M>** extends Product<T,M> {..}
추가적인 타입 파라미터도 가질 수 있다
public class ChildProduct<T,M,C> extends Product<T,M> {..}
*제네릭 인터페이스를 구현할 경우
*제네릭 인터페이스를 구현한 클래스도 제네릭 타입으로!
PECS 원칙 // 공부 다시하자 먼말인지몰겟다.
Producers는 Extends, Consumer는 Super
| keyword | role | 목적 | 예시타입 | 설명 |
| ? extends T | Producer | 읽기전용 | List< ? extends Number> | 생산된 걸 꺼내어 쓰는 입장. 안전하게 꺼낼 수 있음. |
| ? super T | Consumer | 쓰기전용 | List <? super integer> | 소비자에게 값을 제공하는 입장. 쓰기전용 |
PEGCSA
producer extends get/ customer super add!
Collection = 자바에서 구현한 자료구조 클래스
colletion에는 get 이 없다!!!!!! (.get이 없음)
객체를 효율적으로 추가, 삭제, 검색할 수 있도록 제공되는 라이브러리
리스트(list), 스택(stack), 큐(queue), 집합(set), 해쉬 태이블(hash table) 등
java.util 에 포함. 컬렉션 클래스&인터페이스로 제공
인터페이스들
- `Collection` :모든 자료구조의 부모 인터페이스, 객체의 모임을 나타냄.
- `Set` : 집합(중복된 원소를 가지지 않는) 자료 구조
- `List` : 순서가 있는 자료 구조, 중복 원소 가능
- `Map` : 키, 값(key,value)이 연관되어있는 사전과 같은 자료 구조 / 유사 파이썬 딕셔너리
- `Queue` : 극장에서의 대기줄과 같이 들어온 순서대로 나가는 자료 구조.
Collection != 배열
List 인터페이스를 ArrayList 와 LinkedList가 구현 (인터페이스의 인터페이스!)
Collection은 List계열과 Set계열로 나뉜다.
Map은 컬렉션이 아니다.

ArrayList
List컬렉션 : 인덱스로 관리하며 중복 객체저장 가능 ... 구현한 클래스 중 하나가 ArrayList
ArrayList : 배열(Array)의 향상된 버전 또는 가변 크기의배열 (크기 고정도 가능하다)
List<E> list = new ArraList<E>(); //생성
List<String> list = Arrays.asList(new String[size]); // 일반 배열을 리스트로 변환
//추가는 list.add("milk");
list.add(1,"apple");
인덱스 1번 자리에 apple을 삽입한다.
list.set(2, "banana");
인덱스 2번 자리를 banana로 대체한다.
list.remove(3); //인덱스 3번 원소를 삭제한다.
======
List 컬렉션 : Vector와 LinkedList
Vector
스레드 동기화(synchronizatio)에 적용된다.
복수의 스레드가 동시에 Vector에 접근해 객체를 추가하거나 삭제하더라도 안전하다.
List<E> list = new Vector<E>();

LinkedList
인접 참조를 링크해서 체인처럼 관리한다.
특정 인덱스에서 객체를 제거하거나 추가하게 되면 바로 앞뒤 링크만 변경한다.
빈번한 객체 삭제와 삽입이 일어나는 곳에서는 ArrayList보다 좋은 성능
List<E> list = new LinkedList<E>();

| 구분 | ArrayList | LinkedList |
|---|---|---|
| 공통점 | - 둘 다 List 인터페이스 구현- 인덱스로 접근 가능 | - 둘 다 순서를 유지- 중복 허용 |
| 데이터 구조 | 배열 기반 | 노드 기반(연결 리스트) |
| 접근 속도 | 빠름 (O(1) 인덱스로 바로 접근) | 느림 (O(n) 처음부터 탐색 필요) |
| 삽입/삭제 속도 | 느림 (중간 삽입/삭제 시 요소 이동 필요) | 빠름 (중간 삽입/삭제 시 링크만 수정) |
| 메모리 사용량 | 상대적으로 적음 | 상대적으로 많음 (포인터 저장 공간 필요) |
2. 어떤 경우에 LinkedList를 사용해야 하나요?
👉 빈번하게 삽입/삭제가 발생하는 경우에 적합합니다.
예시 상황:
- 큐(Queue), 덱(Deque)처럼 양쪽에서 요소를 자주 넣고 빼야 하는 경우
- 리스트 중간에 자주 삽입하거나 삭제하는 작업이 있는 경우
- 요소를 순차적으로 처리하며, 인덱스 접근이 중요하지 않을 때
반대로, 랜덤 접근(인덱스 기반)이 잦은 경우는 ArrayList가 유리합니다.
3. 기존 배열을 List처럼 다룰 수 있을까?
yes!
자바에서는 Arrays.asList() 메서드를 통해 배열을 List처럼 다룰 수 있다.
'컴퓨터공학과 > Java 1 & 2' 카테고리의 다른 글
| JAVA프로그래밍및실습/최윤정교수님/기말고사 범위 (0) | 2025.06.08 |
|---|---|
| Battle 과제 코드 수정 - 공격/힐링 모듈화 + 레벨업 모듈화 (0) | 2025.05.30 |
| JAVA프로그래밍 및 실습I 과제#7예외처리 조사 및 사용하기 (0) | 2025.05.17 |
| [문제해결] 이클립스 패키지탐색기에서 파일이 열리는 경우 (0) | 2025.05.17 |
| JAVA 프로그래밍 및 실습 I - [과제#6] String클래스 조사 및 사용하기(Summary포함) (0) | 2025.05.17 |