티스토리 뷰

Java/이론

제네릭(Generic)

0bliviat3 2023. 10. 4. 22:28

왜 제네릭을 사용하는가?


 

컴파일시 강한 타입체크를 할 수 있다.

 

제네릭 타입 선언을 통해 실행 전 컴파일시 미리 타입을 강하게 체크해 에러를 사전에 방지할수 있다.

 

불필요한 형변환을 줄일수 있다.

 

제네릭을 사용한다면 실행전 타입을 강제할수 있어 실행중 형변환을 통해

원하는 타입으로 형변환하는것이 아닌

이미 원하는 타입의 자료형으로 실행시킬수 있다.

 

즉 특정 타입의 정해진 자료형을 형변환을 사용해 데이터를 다루는것이 아닌

사용자가 지정하는 타입으로 지정된 자료형으로 자유롭게 데이터를 다룰수 있다.

 

만약 내가 사용하려는 임의의 자료구조가 Integer 타입으로만 사용이 가능하게 설계가 되었다면,

해당 자료구조로 Double 형의 연산을 하고싶다면 그때 그때 형변환을 통해 사용해야 할것이다.

그러나 제네릭을 사용한 자료구조라면 처음부터 Double 형으로 지정해 사용하면 된다. 

 

예시를 들자면 많이들 사용하는 ArrayList의 경우,

선언할때 ArrayList<타입> 변수명 = new ArrayList<>(); 의 형태로 선언하는 것은 다들 알것이다.

이때 <타입> 의 꼴로 사용자가 임의로 지정한 타입으로

데이터를 다루기 때문에 불필요한 형변환을 하지 않는것이다.

 

 

 

 


 

 

타입 파라미터 네이밍 규칙(Type Parameter Naming Conventions)


 

먼저 제네릭에 대한 공식문서를 보면,

 

https://docs.oracle.com/javase/tutorial/java/generics/types.html

 

타입 파라미터에 대한 네이밍 규칙도 나름 정해져 있다는 것을 알수있다.

이는 변수명규칙, 클래스명 규칙같이 개발자들간의 하나의 약속이다 생각하고 넘어가면 될듯하다.

 

type parameter most commonly used
E element
K key
N number
T type
V value
S,U,V etc... 2nd, 3rd, 4th types

 

 

 

제네릭타입 클래스, 인터페이스


 

제네릭 타입을 타입을 파라미터로 갖는 클래스와 인터페이스를 말한다.

 

클래스나 인터페이스 선언시 <타입> 키워드를 붙여서 선언해주면 된다.

 

public class 클래스명<T> { ... }
public interface 인터페이스명<T> { ... }

 

추상화 단계 즉 선언시에는 위와같이 네이밍 규칙에 따라 선언을 하고

실제 객체를 생성하거나 코드에서 사용시에는 명확한 자료형을 지정해 사용하면 된다.

 

예를 들어 String형으로 사용하고 싶다면 다음과 같이 사용하면 될것이다.

클래스명<String> instance;

 

그럼 실제 어떤식으로 적용되는지 코드로 살펴보도록 하겠다.

 

먼저 다음과 같이 getter,setter를 갖는 제네릭타입 클래스를 하나 선언해주도록 하겠다.

 

public class Box<T> {
	private T t;
	public T get() { return t; }
	public void set(T t) { this.t = t; };
}

 

Box 클래스의 객체를 생성해 데이터를 저장한다고 가정하면,

 

		Box<Integer> box1 = new Box<Integer>();
		box1.set(100);
		int intValue = box1.get();
		
		
		Box<String> box2 = new Box<>();
		box2.set("test");
		String strValue = box2.get();

 

String , Integer 모두 지정해주기만 한다면

같은 클래스임에도 다른 자료형의 데이터를 다루기 용이하다는 것을 알 수 있다.

 

이는 String, Integer 클래스에만 국한되는것이 아닌 다른 모든 객체에 대해서도 똑같이 적용해 사용할수 있다.

 

또한 객체 생성시 명시적으로 타입을 지정해주어도 되지만,

box2와 같이 타입 파라미터를 추정하게끔 할 수도 있다.

 

제네릭을 사용하지 않고 해당 코드를 작성한다면

Object 타입으로 데이터를 받아 각각 형변환해 사용해야 할것을 

제네릭으로 퉁쳐버리는 강력함을 맛볼수 있다.

 

 

 

그리고 많이들 사용하는 map과 같은 자료구조의 경우

두가지의 제네릭 타입을 사용한다는것을 생각해본다면,

 

이를 응용하여 멀티타입 파라미터로도 적용이 된다는 것을 알 수 있다.

 

public class testMap<K,V> { ... }
public interface multiTest<K,V,S> { ... }

 

 

 

 

제네릭 메소드


 

제네릭 클래스, 인터페이스와 마찬가지로 메소드 역시 제네릭 타입을 사용해 선언이 가능하다.

 

public <타입 파라미터> 리턴타입 메소드명(매개변수, ... ) { ... }

 

간단한 예시를 들어 설명하자면,

 

인자로 받는 두값이 같은지 확인하는 메소드를 만든다고 생각해보겠다.

 

<> 기호안에 타입 파라미터 V를 기입 후 매개변수 타입으로 V를 사용해 

v1과 v2를 비교한 결과를 boolean 타입으로 리턴해준다면 다음과 같다.

 

	public <V> boolean equals(V v1, V v2) {
		return v1.equals(v2);
	}

 

 

 

 

타입 파라미터의 제한


 

타입 파라미터에 지정되는 구체적인 타입을 때로는 특정 클래스에서 상속을 받는 클래스로만 제한한다던가

혹은 상위클래스로만 제한한다던가 하는등의 경우엔 다음과 같이 제한이 가능하다.

 

public <T extends 상위타입> 리턴타입 메소드명(매개변수, ...) { ... }
public <T super 하위타입> 리턴타입 메소드명(매개변수, ...) { ... }

 

첫번째 줄은 상위클래스에는 제한을 두어

상위타입 자기자신을 포함한 하위 클래스만으로 제한을 거는 방법이고

 

두번째 줄은 하위클래스에 제한을 두고

하위타입 자기자신을 포함한 상위클래스만으로 타입에 제한을 거는 방법이다.

 

그리고 와일드 카드라고 불리는 알수 없는 유형을 의미하는 ? 키워드를 사용해

선언하는 방식도 가능하다.

 

공식문서에는 구체적으로 작성하는것을 권고하지만 그럴수 없는 경우 사용하면 될듯하다.

 

<?>
<? extends 상위타입>
<? super 하위타입>

 

 

부가적으로 설명하자면 <? extends Number> 라고 사용하게 된다면,

Number 클래스를 포함한 그리고 Number 클래스를 상속받는

AtomicInteger, AtomicLong, BigDecimal, BigInteger, 

Byte, Double, DoubleAccumulator, DoubleAdder, Float, Integer, Long, LongAccumulator, LongAdder, Short

등의 서브클래스로만 제한 하여 사용한다는 의미이고

 

<? super Number> 라고 사용하게 된다면,

 

Number 클래스와 Number 클래스의 슈퍼클래스인 Object만으로 제한하여 사용한다는 것이다.

 

또한 extends 키워드를 사용했다고 해서

클래스에만 국한되는것이 아닌 인터페이스도 마찬가지로 적용이 가능하다.

 

 


 

 

 

제네릭은 개념적인 부분은 크게 어렵지 않지만

실제 코드작성시 상속받고 인터페이스를 구현받아 사용하는등

여러 가지 복합적인 요소를 고려해 사용한다면 쉽게 느껴지진 않을듯 하다.

 

그러나 매우 강력한 기능을 갖고,

컬렉션 프레임워크, 람다식, 스트림등에서 널리 사용되면서

공식문서에서도 제네릭 표현이 많으므로

반드시 숙지하고 넘어가야 한다.

'Java > 이론' 카테고리의 다른 글

Enum  (0) 2023.11.24
함수형 인터페이스 (JAVA)  (0) 2023.11.17
연산자 (Operator)  (0) 2023.09.20
형 변환(casting)  (0) 2023.09.17
단순자료형  (0) 2023.09.17
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/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
글 보관함