1-3. 제네릭 용어와 관례

shin·2024년 6월 16일

제네릭의 핵심은 사용할 타입을 미리 결정하지 않는다는 점

  • 클래스 내부에서 사용하는 타입을 클래스를 정의하는 시점에 결정하는 것이 아니라 실제 사용하는 생성 시점에 타입을 결정하는 것임
  • 메서드의 매개변수와 인자의 관계와 비슷함

메서드에 필요한 값을 메서드 정의 시점에 미리 결정

void method1() {
	printIn("hello");
}
  • 메서드에 필요한 값을 이렇게 메서드 정의 시점에 결정하게 되면, 이 메서드는 오직 "hello"라는 값만 출력할 수 있음
  • 따라서 재사용성이 떨어지게 됨

메서드에 필요한 값을 인자를 통해 매개변수로 전달해서 결정

 void method2(String param) {
 	println(param);
 }
 
 void main() {
 	method2("hello");
 	method2("hi");
 }
  • 메서드에 필요한 값을 메서드를 정의하는 시점에 미리 결정하는 것이 아니라, 메서드를 실제 사용하는 시점으로 미룰 수 있음
  • 메서드에 매개변수(String param)를 지정하고, 매서드를 사용할 때 원하는 값을 인자("hello", "hi")로 전달하면 됨

다양한 값을 처리하는 메서드

//method2("hello") 호출 예
void method2(String param="hello") {
 	println(param);
}

//method2("hi") 호출 예
void method2(String param="hi") {
 	println(param);
}
  • 매개변수를 정의하고, 실행 시점에 인자를 통해 원하는 값을 매개변수에 전달
  • 이렇게 하면 이 메서드는 실행 시점에 얼마든지 다른 값을 받아서 처리할 수 있음
  • 따라서 재사용성이 크게 늘어남

메서드의 매개변수와 인자

void method(String param) // 매개변수

void main() {
 	String arg = "hello";
 	ethod(arg) //인수 전달
}
  • 매개변수(Parameter) : String param
  • 인자, 인수(Argument) : arg
  • 메서드의 매개변수에 인자를 전달해서 메서드의 사용 값을 결정함

제네릭의 타입 매개변수와 타입 인자

  • 제네릭도 앞서 설명한 메서드의 매개변수와 인자의 관계와 비슷하게 작동함

  • 제네릭 클래스를 정의할 때 내부에서 사용할 타입을 미리 결정하는 것이 아니라, 해당 클래스를 실제 사용하는 생성 시점에 내부에서 사용할 타입을 결정하는 것임

  • 차이가 있다면 메서드의 매개변수는 사용할 값에 대한 결정을 나중으로 미루는 것이고, 제네릭의 타입 매개변수는 사용할 타입에 대한 결정을 나중으로 미루는 것임


정리하면,

  • 메서드의 매개변수인자를 전달해서 사용할 값을 결정함
  • 제네릭 클래스는 타입 매개변수타입 인자를 전달해서 사용할 타입을 결정함

  • 제네릭에서 사용하는 용어도 매개변수, 인자의 용어를 그대로 가져다 사용함

  • 다만 값이 아니라 타입을 결정하는 것이기 때문에 앞에 타입을 붙임

    • 타입 매개변수: GenericBox<T>에서 T
    • 타입 인자:
      • GenericBox<Integer>에서 Integer
      • GenericBox<String>에서 String
  • 제네릭 타입의 타입 매개변수 <T>에 타입 인자를 전달해서 제네릭 사용 타입을 결정함

    GenericBox<T>

    • String -> GenericBox<String>
    • Integer -> GenericBox<Integer>


용어 정리

제네릭(Generic) 단어

  • 제네릭이라는 단어는 일반적인, 범용적인이라는 영어 단어 뜻임
  • 풀어보면 특정 타입에 속한 것이 아니라 일반적으로, 범용적으로 사용할 수 있다는 뜻

제네릭 타입(Generic Type)

  • 클래스나 인터페이스를 정의할 때 타입 매개변수를 사용하는 것을 말함
  • 제네릭 클래스, 제네릭 인터페이스를 모두 합쳐서 제네릭 타입이라고 함
    • 타입은 클래스, 인터페이스, 기본형(int등)을 모두 합쳐서 부르는 말
  • 예 : class GenericBox<T> { private T t; }
    • 여기에서 GenericBox<T>를 제네릭 타입이라고 함

타입 매개변수(Type Parameter)

  • 제네릭 타입이나 메서드에서 사용되는 변수로, 실제 타입으로 대체됨
  • 예 :GenericBox<T>
    • 여기에서 T를 타입 매개변수라고 함

타입 인자(Type Argument)

  • 제네릭 타입을 사용할 때 제공되는 실제 타입
  • 예 : GenericBox<Integer>
    • 여기에서 Integer를 타입 인자라고 함


제네릭 명명 관례

  • 타입 매개변수는 일반적인 변수명처럼 소문자로 사용해도 문제는 없음
  • 하지만 일반적으로 대문자를 사용하고 용도에 맞는 단어의 첫글자를 사용하는 관례를 따름

주로 사용하는 키워드

  • E - Element
  • K - Key
  • N - Number
  • T - Type
  • V - Value
  • S,U,V etc. - 2nd, 3rd, 4th types

제네릭 기타

  • 다음과 같이 한 번에 여러 타입 매개변수를 선언할 수 있음
class Data(K, V) {}
  • 타입 인자로 기본형은 사용할 수 없음
    • 제네릭의 타입 인자로 기본형(int, double...)은 사용할 수 없음
    • 대신 래퍼 클래스(Integer, Double)를 사용하면 됨

raw type

package generic.ex1;

public class RawTypeMain {

	public static void main(String[] args) {
    
 		GenericBox integerBox = new GenericBox();
        //GenericBox<Object> integerBox = new GenericBox<>(); // 권장
        integerBox.set(10);
 		Integer result = (Integer) integerBox.get();
 		System.out.println("result = " + result);
    }
 }

실행 결과

result = 10

  • 제네릭 타입을 사용할 때는 항상 <>를 사용해서 사용 시점에 원하는 타입을 지정해야 함
  • 그런데 아래와 같이 <>을 지정하지 않을 수 있는데, 이런 것을 raw type 또는 원시 타입이라고 함
GenericBox integerBox = new GenericBox();
  • 원시 타입을 사용하면 내부의 타입 매개변수가 Object로 사용된다고 이해하면 됨

  • 제네릭 타입을 사용할 때는 항상 <>를 사용해서 사용시점에 타입을 지정해야 하는데, 이런 raw 타입을 지원하는 이유

    • 자바의 제네릭이 자바가 처음 등장할 때부터 있었던 것이 아니라, 자바가 오랜기간 사용된 이후에 등장했기 때문

    • 제네릭이 없던 시절의 과거 코드와의 하위 호환이 필요했음

    • 따라서 어쩔 수 없이 이런 raw type을 지원함


  • 결론적으로 raw type을 사용하지 않는 것이 권장됨

    • 만약 Object 타입을 사용해야 한다면, 아래와 같이 타입 인자로 Object를 지정해서 사용하는 것이 권장됨
GenericBox<Object> integerBox = new GenericBox<>();


강의 출처 : 김영한의 실전 자바 - 중급 2편

profile
Backend development

0개의 댓글