#1 교육정리
1) Generic
2) Iterator
#2 Generic
자바에서 제네릭(generic)이란 데이터의 타입(data type)을 일반화한다(generalize)는 것을 의미합니다.
제네릭은 클래스나 메소드에서 사용할 내부 데이터 타입을 컴파일 시에 미리 지정하는 방법입니다.
이렇게 컴파일 시에 미리 타입 검사(type check)를 수행하면 다음과 같은 장점을 가집니다.
클래스 내부에서 사용할 데이터 타입을 외부에서 지정하는 기법을 의미하며, 객체별로 다른 타입의 자료가 저장될 수 있도록 합니다.
즉, 데이터 형식에 의존하지 않고, 하나의 값이 여러 다른 데이터 타입들을 가질 수 있도록 하는 방법 입니다.
JDK 1.5 이전에서는 여러 타입을 사용하는 대부분의 클래스나 메소드에서 인수나 반환값으로 Object 타입을 사용했습니다.
하지만 이 경우에는 반환된 Object 객체를 다시 원하는 타입으로 타입 변환해야 하며, 이때 오류가 발생할 가능성도 존재합니다.
하지만 JDK 1.5부터 도입된 제네릭을 사용하면 컴파일 시에 미리 타입이 정해지므로, 타입 검사나 타입 변환과 같은 번거로운 작업을 생략할 수 있게 됩니다.
Generic 사용의 장점)
1. 제네릭을 사용하면 잘못된 타입이 들어올 수 있는 것을 컴파일 단계에서 방지하여 안정성을 높일 수 있습니다.
2. 클래스 외부에서 타입을 지정해주기 때문에 따로 타입을 체크하고 변환해줄 필요가 없다. 즉, 관리하기가 편하다.
3. 비슷한 기능을 지원하는 경우 코드의 재사용성이 높아진다.
Generic Type)
명명하고 싶은대로 아무 단어나 넣어도 문제는 없지만, 대중적으로 통하는 통상적인 네이밍이 있으면 개발이 용이해 지기 때문에 아래 표화 같은 암묵적인 규칙(convention)이 존재한다
타입 | 설명 |
<T> | 타입(Type) |
<E> | 요소(Element) |
<K> | 키(Key) |
<V> | 리턴 값 또는 매핑된 값(Variable) |
<N> | 숫자(Number) |
<S, U, V> | 2번째, 3번째, 4번째 선언된 타입 |
사용 문법)
배열과 리스트의 선언문 형태를 비교해보면 이해하기 쉬울 것이다. 선언하는 키워드나 문법 순서가 다를뿐, 결국 자료형명을 선언하고 자료형의 타입을 지정한다는 점은 같다고 볼 수 있다.
이처럼 제네릭은 배열의 타입을 지정하듯이 리스트 자료형 같은 컬렉션 클래스나 메소드에서 사용할 내부 데이터 타입(type)을 파라미터(parameter) 주듯이 외부에서 지정하는 이른바 타입을 변수화 한 기능이라고 이해하면 된다.
즉, 우리가 변수를 선언할때 변수의 타입을 지정해주듯이, 제네릭은 객체(Object)에 타입을 지정해주는 것이라고 보면 된다.
위에서 보다시피, 제네릭은 <> 꺾쇠 괄호 키워드를 사용하는데 이를 다이아몬드 연산자라고 한다. 그리고 이 꺾쇠 괄호 안에 식별자 기호를 지정함으로써 파라미터화 할 수 있다. 이것을 마치 메소드가 매개변수를 받아 사용하는 것과 비슷하여 제네릭의 타입 매개변수(parameter) / 타입 변수 라고 부른다.
이 타입 매개변수는 제네릭을 이용한 클래스나 메소드를 설계할 때 사용된다.
제네릭 클래스를 만들었으면 이를 인스턴스화 해보자. 마치 파라미터를 지정해서 보내는 것 처럼 생성 코드에서 꺾쇠 괄호 안에 지정해주고 싶은 타입명을 할당해주면, 제네릭 클래스 선언문 부분으로 가서 타입 파라미터 T 가 지정된 타입으로 모두 변환되어 클래스의 타입이 지정되게 되는 것이다.
class FruitBox<T> {
List<T> fruits = new ArrayList<>();
public void add(T fruit) {
fruits.add(fruit);
}
}
// 제네릭 타입 매개변수에 정수 타입을 할당
FruitBox<Integer> intBox = new FruitBox<>();
// 제네릭 타입 매개변수에 실수 타입을 할당
FruitBox<Double> intBox = new FruitBox<>();
// 제네릭 타입 매개변수에 문자열 타입을 할당
FruitBox<String> intBox = new FruitBox<>();
// 클래스도 넣어줄 수 있다. (Apple 클래스가 있다고 가정)
FruitBox<Apple> intBox = new FruitBox<Apple>();
이를 그림으로 표현해보면, 다음과 같이 제네릭 타입 전파가 행해진고 보면 된다. <T> 부분에서 실행부에서 타입을 받아와 내부에서 T 타입으로 지정한 멤버들에게 전파하여 타입이 구체적으로 설정 되는 것이다. 이를 전문 용어로 구체화(Specialization) 라고 한다.
제네릭 객체를 사용하는 문법 형태를 보면 양쪽 두 군데에 꺾쇠 괄호 제네릭 타입을 지정함을 볼 수 있다. 하지만 맨 앞에서 클래스명과 함께 타입을 지정해 주었는데 굳이 생성자까지 제네릭을 지정해 줄 필요가 없다. (중복)
따라서 jdk 1.7 버전 이후부터, new 생성자 부분의 제네릭 타입을 생략할 수 있게 되었다. 제네릭 나름대로 타입 추론을 해서 생략 된 곳을 넣어주기 때문에 문제가 없는 것이다.
FruitBox<Apple> intBox = new FruitBox<Apple>();
// 다음과 같이 new 생성자 부분의 제네릭의 타입 매개변수는 생략할 수 있다.
FruitBox<Apple> intBox = new FruitBox<>();
#3 Iterator
Iterator<E> 인터페이스)
자바의 컬렉션 프레임워크는 컬렉션에 저장된 요소를 읽어오는 방법을 Iterator 인터페이스로 표준화하고 있습니다.
Collection 인터페이스에서는 Iterator 인터페이스를 구현한 클래스의 인스턴스를 반환하는 iterator() 메소드를 정의하여 각 요소에 접근하도록 하고 있습니다.
따라서 Collection 인터페이스를 상속받는 List와 Set 인터페이스에서도 iterator() 메소드를 사용할 수 있습니다.
또한, "반복"이 루핑에 대한 기술 용어이기 때문에 "반복자"라고 합니다.
정리하자면, Java에서 제공하는 컬렉션은 보관하고 있는 자료들을 순차적으로 접근하면서 처리할 때 사용하는 Iterator 형식을 제공하고 있습니다. Iterator는 반복자라고 부르며 컬렉션 종류에 관계없이 같은 방법으로 프로그래밍 할 수 있게 해 줍니다
Java API 에서는 아래와 같이 설명하고 있습니다.
Interface Iterator<E>
- Type Parameters:E - the type of elements returned by this iteratorAll Known Subinterfaces:ListIterator<E>, PrimitiveIterator<T,T_CONS>, PrimitiveIterator.OfDouble, PrimitiveIterator.OfInt, PrimitiveIterator.OfLong, XMLEventReaderAll Known Implementing Classes:BeanContextSupport.BCSIterator, EventReaderDelegate, Scanner
public interface Iterator<E>
An iterator over a collection. Iterator takes the place of Enumeration in the Java Collections Framework. Iterators differ from enumerations in two ways:- Iterators allow the caller to remove elements from the underlying collection during the iteration with well-defined semantics.
- Method names have been improved.
This interface is a member of the Java Collections Framework.
https://docs.oracle.com/javase/8/docs/api/java/util/Iterator.html
Iterator 인터페이스는 다음과 같은 메소드를 사용하여 컬렉션의 각 요소에 접근할 수 있습니다.
메소드 | 설명 |
boolean hasNext() | 해당 이터레이션(iteration)이 다음 요소를 가지고 있으면 true를 반환하고, 더 이상 다음 요소를 가지고 있지 않으면 false를 반환함. |
E next() | 이터레이션(iteration)의 다음 요소를 반환함. |
default void remove() | 해당 반복자로 반환되는 마지막 요소를 현재 컬렉션에서 제거함. (선택적 기능) |
정의방법)
정의방법은 Iterator<T> iterator = Collection.iterator(); 이고,
메서드는 다음 요소가 있는지 판단하는 hasNext(), 다음 요소를 가져오는 next(), 가져온 요소를 삭제하는 remove()가 끝이다.
public class IteratorTest {
public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>();
for(int i = 0;i <= 100; i++) {
list.add(i);
}
Iterator<Integer> iter = list.iterator();
while(iter.hasNext()) {
int data = iter.next();
System.out.print(data);
}
}
}
코드예제 참조 : https://tlatmsrud.tistory.com/61
5~9번 라인에서 Collection 인터페이스를 상속받는 ArrayList 객체를 생성하고 0부터 100 값을 add 한다.
11번 라인에서 Iterator<T> iterator = Collection.iterator(); 형식에 맞게 Iterator<Integer> iter = list.iterator(); 를 사용하여 Iterator를 참조한다.
13번 라인에서 hasNext() 메서드를 사용하여 다음 요소가 있는지 확인한다. (있으면 true, 없으면 false를 반환)
14번 라인에서 next() 메서드를 사용해 다음 요소의 값을 조회한다.
'[Naver Cloud Camp 7] 교육 정리' 카테고리의 다른 글
네이버 클라우드 캠프 45일차 230628 (0) | 2023.06.28 |
---|---|
네이버 클라우드 캠프 44일차 230627 (0) | 2023.06.27 |
네이버 클라우드 캠프 42일차 230623 (1) | 2023.06.24 |
네이버 클라우드 캠프 41일차 230622 (0) | 2023.06.22 |
네이버 클라우드 캠프 40일차 230621 (0) | 2023.06.21 |