코코무의 코딩캔버스

[Java] 제네릭(Generic) 본문

Java

[Java] 제네릭(Generic)

코코무 2024. 1. 4. 10:33
제네릭 (Generic)

 

  • Meaning
  • 일반적인
  • 데이터 형식에 의존하지 않고, 하나의 값이 여러 다른 데이터 타입들을 가질 수 있도록 하는 방법
  • 클래스 내부에서 지정하는 것이 아닌 외부에서 사용자에 의해 지정되는 것을 의미

 


  • 자바(Java)의 제네릭(Generic)
  • Java 5.0부터 도입, 클래스나 메소드에서 사용할 데이터 타입을 일반화하는 방법
  • 잘못된 타입이 사용될 수 있는 문제를 컴파일 과정에서 제거할 수 있도록 구현
  • 쓰임새
    • 컬렉션, 람다식, 스트림, NIO, API 도큐먼트 JAVA 도움말
  • 형식
객체<타입> 객체명 = new 객체<타입>();

 

  • 클래스와 인터페이스, 메소드를 정의할 때 타입(type)을 파라미터(parameter)로 사용할 수 있게 함
  • 장점

 1. 타입 안정성(Type Safety)

   1) 컴파일 단계에서 들어오는 잘못된 타입을 체크 및 방지

   2) 따로 타입을 체크하고 변환할 필요 없음(클래스 외부에서 타입을 지정하기 때문)

 2. 타입변환 제거(형변환 감소)

   비제네릭 코드: 불필요한 타입 변환으로 코드 가독성과 유지보수성을 높임

List list = new ArrayList(); // 비제네릭 코드
list.add("hello");

String str = (String) list.get(0); // 강제타입변환을 해야 문자열 얻기 가능
--------------------------------------------------------------------------
List<String> list = new ArrayList<String>(); // 제네릭 코드
list.add("hello");

String str = list.get(0); // 객체 생성 시 <String>을 사용해서 강제로 String 타입 명시

>> 비제네릭 코드와 제네릭 코드

ArrayList<Integer> list1 = new ArrayList<Integer>();
ArrayList<String> list2 = new ArrayList<Integer>();
LinkedList<Double> list3 = new LinkedList<Double>():
LinkedList<Character> list4 = new LinkedList<Character>();

>> 제네릭 코드의 여러가지 생성 방식

 2. 코드 재사용성(Reusability)

  다양한 타입에 대해 동일한 코드 재사용 가능


  • 제네릭(Generic) 타입(class<T>, interfact<T>)
  • 타입을 파라미터(parameter, 매개변수)로 가지는 클래스(class)와 인터페이스(interface)가 있는데 클래스 또는 인터페이스 이름 뒤에 < > 부호가 붙고 사이에 타입 파라미터가 위치
public class 클래스명<T> {//실행문}
public interface 인터페이스명<T> {//실행문}
  • 타입 파라미터 표기법: 대문자 알파벳 한 글자
public class Box {
	//필드
	private Object object;
    //메서드
    public void set(Object object) {this.object = object;}
    public Object get() {return object;}
    }
  • Box 클래스의 필드 타입이 Object인데, Object 타입으로 선언한 이유: 필드에 모든 종류의 객체를 저장하기 위함
  • Object 클래스는 모든 자바 클래스의 최상위 클래스
  • 자식 객체는 부모 타입에 대입할 수 있다는 성질 때문에 모든 자바 객체는 Object 타입으로 자동타입변환 되어 저장
Object object = 자바의 모든 객체;

 


  • 제네릭의 타입변환
Box<String> box = new Box<String>(); // 강제로 String 타입만 적용
Box<Integer> boxl = new Box<Integer>(); // 강제로 Integer 타입만 적용

>> 타입 파라미터 T를 사용해서 Object 타입을 모두 T로 대체 (T는 Box 클래스로 객체를 생성할 때 구체적인 타입으로 변경됨)

 

String name = box.get(); // 강제 타입변환 없음
int value = boxI.get() ; // 강제 타입 변환 없이 정수형을 사용

>> main 메서드에서 강제타입변환 없이 사용

 


  • 멀티 타입 파라미터(Multi-type Parameter)(class<K, V...>)
  • 두 개 이상 사용 가능(콤마로 구분)
  • Java 7.0부터 중복 기술 감소를 위해 다이아몬드 연산자 제공
new Product<>; // 타입 명시를 생략 가능

 


  • 제네릭 메서드(Generic Method)(<T, R> R method(T t))
  • 매개 타입과 리턴 타입으로 타입 파라미터를 갖는 메소드
  • 선언 방법: 리턴 타입 앞에 < > 기호 추가  → 타입 파라미터 기술 → 매개 변수 타입으로 T 사용, 리턴 타입으로 제네릭 타입 Box<T> 사용
public <타입파라미터, ...> 리턴타입 메소드명(매개변수, ...) {//실행문}
  • boxing() 제네릭 메소드: < > 기호 안에 타입 파라미터 T 기술 → 매개 변수 타입으로 T 사용, 리턴 타입으로 제네릭 타입 Box<T> 사용
public <T> Box <T> boxing(T t) {...}

 

  • 사용예시
public class Util {
    public static <T> void printArray(T[] array) {
        for (T element : array) {
            System.out.println(element);
        }
    }
}

Integer[] intArray = {1, 2, 3, 4, 5};
Util.printArray(intArray);

String[] stringArray = {"A", "B", "C"};
Util.printArray(stringArray);

제네릭은 코드의 재사용성과 타입 안전성을 크게 향상시키는 기능으로서, 개발자는 이를 통해 더 간결하고 오류가 적으며, 유지보수하기 쉬운 코드를 작성할 수 있다.