제네릭 스택의 구조
임의의 객체를 담을 수 있는 제네릭 스택의 구조를 살펴보자.
- 제네릭 클래스는 클래스명 뒤에 <Type>과 같은 파라미터를 붙여서 선언한다.
- 제네릭 스택 사용 이유: 임의의 객체를 스택(배열)에 담을 수 있다.
대략적인 구조
- 스택 관련 필드
- 스택 관련 메서드
- 예외처리 부분
- 생성자
간단히 보자면 아래와 같다.
public class Gstack<E> { //제네릭 클래스로 선언되어있다.
private int max; // 스택의 용량
private int ptr; // 스택 포인터
private E[] stk; // 스택 본체
// 생성자
public Gstack(int capacity) {
ptr = 0;
max = capacity;
try {
stk = (E[]) new Object[max]; // 스택 본체용 배열을 생성
} catch (OutOfMemoryError e) { // 예외 처리, 생성불가능
max = 0;
}
}
.
.
// 실행시 예외 관련 작성부: 스택이 가득 찼을 경우, 스택이 비어있을 경우
.
.
// push, pop, peek 등 스택관련 매소드 작성부
.
.
}
이렇게 스택을 제네릭으로 만들었을 경우 유의해야 할 부분을 짚어보자.
제네릭 배열생성시 발생하는 문제를 유의하자
원래 '실체화 불가 타입'에 대한 배열은 생성할 수 없다. 제네릭은 실체화 불가 타입이다.
다음 글에서 제네릭과 배열의 차이점, 그리고 제네릭 배열을 생성하지 못하는 이유에 대해 잘 정리해 놓으셨다. 좋은 공부가 될 듯하니 꼼꼼히 읽어보자.
(1. 배열은 공변, 제네릭은 불공변 / 2. 배열은 런타임에 실체화, 제네릭 타입은 런타임에 소거)
위와 같은 이유로 제네릭 배열을 일반적인 방법으로 만드는 것이 통할 수 없다. 그래서 제네릭 배열을 만들어야 할 때는 형변환(강제캐스팅)하는 방식이 필요하다. 이 형변환의 결과가 타입안전성을 해치지 않음을 우리가 판단해야 하고, 타입 안전함을 확인했다면 올바른 제네릭타입 배열 완성!
알고 넘어가자:
※ 제네릭형으로 생성자를 호출할 수 없다.
예를 들면 Gstack<E>라는 제네릭 클래스 내부에서 new E()와 같은 생성자를 호출할 수 없다. 제네릭은 데이터 타입이 런타임 시점에 동적으로 결정된다. 즉, 제네릭은 컴파일 타임에 결정할 수 없으므로 new E()와 같은 생성자의 사용이 불가능하다.
그냥 배열에 제네릭타입 말고 Object타입이 들어가게 구현하면 안 될까?
스택을 제네릭클래스로 선언하지 말고, 스택에 최상위 클래스인 Object가 들어가게끔 하면 되지 않을까 하는 궁금증이 생긴다. 하지만 이렇게 했을 때 큰 문제점이 있다.
배열의 요소에 Object가 들어가게 하면, 그 배열에 Integer가 들어가든 String이 들어가든 배열요소의 타입이 막 섞여도 문법적으로 이상이 없다. 즉, 컴파일 단계에서 잡아낼 수가 없다. 하지만 제네릭 타입을 사용하면 <>안에 사용할 타입을 명시해줄 수 있기 때문에 런타임에러가 아닌 컴파일에러를 일으킬 수 있어서 좋다.
참고:
▷ 컴파일 에러: 말 그대로 컴파일이 불가능하다는 에러. 프로그램을 실행하기 전의 컴파일 단계에서 에러가 발생한다. 문법을 잘못 작성했을 때의 에러이므로 쉽게 교정할 수 있다.
▷ 런타임 에러: 설계를 잘못 해서 프로그램 실행 중에 생기는 에러. 런타임 에러 발생시 원인을 손수 확인하여 해결해야 한다. 대부분 try-catch문으로 에러를 방지할 수 있다. (NullPointerException, 무한루프 등)
다시 보는 제네릭의 장점
- 컴파일시에 타입체크를 하게된다:
따러서 프로그램 실행 중 발생할 수 있는 ClassCastException 등 문제를 애초에 막을 수 있다. 타입에 대한 안정성이 있다고 말한다.
- 제네릭을 통해 가능한 타입을 미리 설정하고 가기 때문에, 추후에 일일이 캐스팅할 필요도 없다.
'자료구조 + 알고리즘' 카테고리의 다른 글
재귀의 제거 | Stack에 잠시 저장해두기 | 재귀의 과정 이해 | 비재귀적 구현해보기 (0) | 2021.07.08 |
---|---|
하나의 배열에 2개의 스택을 구현하기 (2) | 2021.07.03 |
이진 검색 - 중복요소의 맨 앞 인덱스 찾아내기 | 반복문의 유연한 사용이 필요하겠다. (0) | 2021.06.28 |
이진 검색 과정을 출력하는 프로그램 작성하기 (0) | 2021.06.28 |
어떤 key와 일치하는 배열요소와 그 인덱스를 반환하기 (0) | 2021.06.25 |