Java Study

제네릭(Generic)이란?

Z00_HWAN_99 2024. 7. 10. 12:13
728x90
반응형

제네릭

  • 결정되지 않은 타입을 파라미터로 처리하고 실제 사용할 때(인스턴스 생성 시) 파라미터를 구체적인 타입으로 대체시키는 기능.
  • <T>는 T가 타입 파라미터임을 뜻하는 기호.

제네릭 타입

  • 결정되지 않은 타입을 파라미터로 가지는 클래스와 인터페이스.
  • 선언부에 '< >'부호가 붙고 그 사이에 타입 파라미터들이 위치.
  • 타입 파라미터는 일반적으로 대문자 알파벳 한 글자로 표현.
  • 외부에서 제네릭 타입을 사용하려면 타입 파라미터에 구체적인 타입을 지정. 지정하지 않으면 Object 타입이 암묵적으로 사용.

제네릭 메서드

  • 타입 파라미터를 가지고 있는 메서드. 타입 파라미터가 메서드 선언부에 정의.
  • 리턴 타입 앞에 < > 기호 추가하고 타입 파라미터 정의 후 리턴 타입과 매개변수 타입에서 사용.
  • 타입 파라미터 T는 매개값의 타입에 따라 컴파일 과정에서 구체적인 타입으로 대체.

제한된 타입 파라미터

  • 모든 타입으로 대체할 수 없고, 특정 타입과 자식 또는 구현 관계이 있는 타입만 대체할 수 있는 타입 파라미터.
  • 상위 타입은 클래스 뿐만 아니라 인터페이스도 가능.

와일드카드 타입 파라미터

  • 제네릭 타입을 매개값이나 리턴 타입으로 사용할 때 범위에 있는 모든 타입으로 대체할 수 있는 타입 파라미터(?로 표시)

 

클래스에서의 예제

package generic.classEx;

public class GenericEx01 {

  public static void main(String[] args) {
    Box<String> box = new Box<String>();
    box.content = "러브 레터";
    String content = box.content;
    System.out.println(content);

    Box<Integer> box1 = new Box<Integer>();
    box1.content = 100;
    int content1 = box1.content;
    System.out.println(content1);

    Box<Doll> box2 = new Box<Doll>();
    box2.content = new Doll();
    Doll content2 = box2.content;
    System.out.println(content2);

    Product<SmartPhone, String> p1 = new Product<SmartPhone, String>();
    p1.setKind(new SmartPhone());
    p1.setModel("Apple 15 pro max");
    SmartPhone applePhone = p1.getKind();
    String applePhoneModel = p1.getModel();
    System.out.println(applePhone + " : " + applePhoneModel);

    Product<Car, String> c1 = new Product<Car, String>();
    c1.setKind(new Car());
    c1.setModel("Ferrari SF90");
    Car ferrari = c1.getKind();
    String ferrariModel = c1.getModel();
    System.out.println(ferrari + " : " + ferrariModel);
  }
}
package generic.classEx;

public class Box <Z>{
  public Z content; // 해당 Box 안에는 다양한 내용물들이 저장될 수 있으므로 특정 클래스 타입으로 선어할 수 없다.
                    // 그러므로, 모든 타입 즉 모든 클래스의 최상위 부모 클래스로 자동 프로모션 되므로 content 필드에는 어떤 객체도 대입될 수 있다.
}//T는 파라미터 타입(기호)라고 한다.
package generic.classEx;

public class Doll {
  public String name = "미미";
  public String company = "영실업";
}
package generic.classEx;

import lombok.Getter;
import lombok.Setter;

//@Getter
//@Setter
public class Product <K, M> { // 제네릭 타입의 클래스
  private K kind; // 타입 파라미터 K를 kind 필드의 타입으로 사용하겠다.
  private M model; // 타입 파라미터 M를 model 필드의 타입으로 사용하겠다.

  public K getKind() {
    return kind;
  }

  public void setKind(K kind) {
    this.kind = kind;
  }

  public M getModel() {
    return model;
  }

  public void setModel(M model) {
    this.model = model;
  }
}
package generic.classEx;

public class Car {

}
package generic.classEx;

public class SmartPhone {

}

 

인터페이스에서의 예제

package generic.interfaceEx;

public class RentEx {

  public static void main(String[] args) {
    Codi codi = new Codi();
    AirConditioner airConditioner = codi.rent();
    airConditioner.powerOn();
  }
}
package generic.interfaceEx;

public interface Rentable<P> {//다양한 대상을 렌트하기 위한 rent() 메서드의 타입을 타입 파라미터로 지정
  public P rent();

}
package generic.interfaceEx;

public class AirConditioner {
  public void powerOn(){
    System.out.println("공기 청정기 전원을 켭니다.");
  }
}
package generic.interfaceEx;

public class Codi implements Rentable<AirConditioner>{

  @Override
  public AirConditioner rent() {
    return new AirConditioner();
  }
}

 

추가 예제

package generic.genericMethodEx;

import generic.classEx.Doll;

public class GenericBoxEx {

  public static void main(String[] args) {
    Box<Integer> box1 = boxing(100);
    int value1 = box1.getType();
    System.out.println(value1);

    //"포켓몬 포토카드"를 박싱하여 포장해주세요.
    Box<String> box2 = boxing("포켓몬 포토카드");
    //상자에서 포켓몬 포토카드를 꺼내주세요.
    String value2 = box2.getType();
    System.out.println(value2);

    //상자에서 미미 인형을 꺼내서 이름과 제조업체를 확인해 주세요.
    Box<Doll> box3 = boxing(new Doll());
    System.out.println(box3.getType().name);
    System.out.println(box3.getType().company);
  }

  public static <T> Box<T> boxing(T t){
    Box<T> box = new Box<T>();
    box.setType(t);
    return box;
  }
}
package generic.genericMethodEx;


public class Box <T>{
  private T type;

  public T getType() { //제네릭 메서드 get
    return type;
  }

  public void setType(T type) { // 제네릭 메서드 set
    this.type = type;
  }
}

 

제네릭을 써야 하는 이유

  • 자바에서 타입의 안정성을 고려 혹은 향상시켜줌.
  • 코드의 재사용성을 증가시킬 수 있음 -> 제네릭을 사용함으로써 개발자는 컴파일 시점에 타입 체크를 할 수 있기 때문.
  • 만약 제네릭을 사용하지 않으면, 컬렉션(자바에서 제공하는 자료구조)은 다양한 객체 타입의 객체를 저장할 수 있는데 이렇게 되면 타입 안정성을 보장해주지 못하며, 객체를 검색하거나 사용할 때마다 타입 비교와 타입 변환의 과정이 필요함.
  • 특정 타입의 객체만 저장할 수 있는 컬렉션을 만들수 있고, 타입 변환 없이 객체 추출 가능.
  • 이로써, 코드의 안정성과 가독성을 향상.

https://github.com/bottomsUp-99?tab=repositories

 

bottomsUp-99 - Overview

Backend Developer. bottomsUp-99 has 9 repositories available. Follow their code on GitHub.

github.com

 

728x90
반응형

'Java Study' 카테고리의 다른 글

java.base 모듈  (0) 2024.07.13
Lamda(람다식)  (0) 2024.07.12
JDBC 라이브러리  (0) 2024.07.07
예외 처리(Exception Handling)  (1) 2024.07.07
인터페이스(Interface)  (0) 2024.07.02