티스토리 뷰

java

[Java] Generics

구삼칠오 2021. 10. 29. 21:55

* Java8 버전의 문법을 기준으로 작성되었습니다.

 

제네릭이란?

무언가에 대해 이해하기 위해선 명확한 정의가 필요하다고 생각합니다. 따라서 몇 가지 레퍼런스들을 찾아보았습니다.

They(Generics) were designed to extend Java's type system to allow "a type or method to operate on objects of various types while providing compile-time type safety".
제네릭은 컴파일 타임 타입 안정성을 제공하면서, 다양한 타입의 객체에서 작동하는 타입 또는 메소드를 허용하도록 Java의 타입 시스템을 확장하도록 설계된 기능이다.
 - Wikipedia / Generics in Java

제네릭의 기능을 한 문장으로 압축하다 보니 문장이 너무 어려워졌지만, 제네릭의 특성을 가장 간결하게 나타낸 문장인 것 같습니다. 하지만 역시 너무 어려우니 우선 넘어가 보겠습니다. 아마 다른 내용들을 모두 보고 나서 다시 천천히 읽어보면 이해하실 수 있을 거라 생각합니다. (저도 그랬습니다....)

 

Generics allow you to abstract over types.
제네릭은 타입을 추상화 할 수 있게 해 줍니다.
 - docs.oracle

아무리 찾아보아도 제네릭에 대한 전반적인 설명은 저 한 문장이 다입니다. 분명 공식 Tutorial의 글인데 불친절 하기 짝이 없습니다. 어쨌든 제네릭은 타입을 추상화해주는 기능이라고 합니다. 다음.

 

제네릭은 다양한 타입의 객체들을 다루는 메소드나 컬렉션 클래스에 컴파일 시의 타입 체크를 해주는 기능이다. 객체의 타입을 컴파일 시에 체크하기 때문에 객체의 타입 안정성을 높이고 형변환의 번거로움이 줄어든다. 타입 안정성을 높인다는 것은 의도하지 않은 타입의 객체가 저장되는 것을 막고, 저장된 객체를 꺼내올 때 원래의 타입과 다른 타입으로 잘못 형변환되어 발생할 수 있는 오류를 줄여준 다는 뜻이다.
 - 자바의 정석 / 남궁성

정리해보자면 제네릭은 자바에서 제공하는 기능 중 하나이며, 타입을 추상화하여 객체와 메소드가 다양한 타입으로 동작하도록 해줍니다. 추상화된 타입은 컴파일 타임에 체크되어 자바의 타입 안정성을 유지해 줍니다. 또한 타입 추상화를 통해 형변환의 번거로움을 없애줍니다.

 

음... 제 나름대로 쉽게 풀어보려 했지만 실패한 것 같습니다..... ㅠ

 

 

제네릭 클래스

Java를 사용하다 보면 많이 접하게 되는 ArrayList의 선언부입니다. ArrayList는 제네릭 클래스로서 클래스명 뒤에 <E>가 붙어있는 것을 볼 수 있습니다. 여기서 E는 타입 변수(Type Variable)라고 하며 이것이 바로 앞에서 이야기한 추상화된 타입입니다. 타입이 변수 형태가 된 것입니다. 그리고 이 타입 변수엔 어떠한 타입도 들어갈 수 있습니다.

 

제네릭 클래스인 ArrayList 객체는 다음과 같이 생성할 수 있습니다.

ArrayList<Integer> intList = new ArrayList<Integer>();  // Integer를 다루는 ArrayList
ArrayList<String> stringList = new ArrayList<String>(); // String을 다루는 ArrayList

< >안에 Integer라는 타입을 명시함으로써 intList는 Integer를 다루는 ArrayList가 되었고, stringList는 String을 다루는 ArrayList객체가 되었습니다. 이제 intList의 타입 변수 E는 Integer로 선언돼 intList 내부에서 사용되는 E type은 모두 Integer type이 될 것입니다. 예를 들어 E type을 반환해주는 get 메소드는 Integer 타입을 반환해주는 것입니다.

 

 

제약사항

제네릭은 어디에나 막 쓸 수 있진 않고 몇 가지 제약사항이 있습니다.

  1. static 타입 변수에는 사용할 수 없습니다. 타입 변수는 인스턴스 변수로 간주되는데 static멤버는 인스턴스 변수를 참조할 수 없기 때문에 사용할 수 없습니다.
  2. 제네릭 타입의 배열을 생성할 수 없습니다. 배열을 생성하기 위해선 new 연산자를 사용해야 하고 new 연산자는 컴파일 타임에 타입이 무엇인지 정확히 알아야 하지만 제네릭 타입은 그렇지 않기 때문에 배열을 생성할 수 없습니다.

 

ref.

자바의 정석

https://en.wikipedia.org/wiki/Generics_in_Java

https://docs.oracle.com/javase/tutorial/extra/generics/intro.html

'java' 카테고리의 다른 글

[JAVA] Reflection  (0) 2022.01.07
[Java] Lambda Expression  (0) 2021.11.08
[Java] Exception Handling  (0) 2021.10.27
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함