JAVA/JAVA

Java | Generic (1) <T>

pathas 2020. 2. 10. 17:04

Generic

Generic Programming: 어떤 값이 하나의 참조 자료형이 아닌
여러 참조 자료형을 사용할 수 있도록 프로그래밍하는 것

  • 여러 개의 참조 자료형을 사용할 수 있도록 할 수 있고,
    특정 자료형만 사용할 수 있도록 제한할 수도 있음
  • 참조 자료형이 변환될 때 이에 대한 검증을 컴파일러가 하므로 안정적임
  • 컬렉션 프레임워크도 많은 부분 제너릭으로 구현

배경

컬렉션에는 모든 자료형이 Object형으로 변환되어 저장되기 때문에
저장된 데이터를 불러올 때 자료형을 각각 지정해주어야 하는 문제가 발생
따라서 처음부터 저장할 자료형을 지정함으로써 편의성을 추구


특징

  • 특정 자료형의 값만 입력 받아서 저장, 조회, 계산, 출력을 가능하게 함
  • 멤버 변수, 메소드 매개변수에도 제너릭 부여 가능
  • 기본 자료형은 사용 불가
  • 컬렉션에 지정된 자료형으로만 데이터 저장 가능
    컬렉션에는 객체만 저장 가능하기 때문에 클래스형 및 Wrapper 클래스만 지정 가능
  • 컬렉션 내부의 데이터를 꺼내올 때 일일이 형 변환할 필요가 없어짐
    → 유지보수에 용이

종류

  • < T > : Type, 클래스 설계시
  • < E > : Element, List 컬렉션에 사용시
  • < K, V > : Key-Value, Map 컬렉션에 사용시
  • < ? > : 메소드 매개변수에만 사용
    매개변수의 자료형을 < ? >로 정의하고 내부에서는
    Object(또는 해당 클래스형)를 사용해서 모든 자료형의 매개변수를 처리할 수 있음

※ 실제로 기능에 차이가 있는 것은 아니고, 사용 위치에 따라 분류되는 것이며
T대신 A나 B와 같은 임의의 문자도 사용 가능 (? 제외)


< > 연산자

< >: 다이아몬드 연산자라고 하며
자료형을 <> 안의 클래스형으로 지정함

컬렉션<객체 종류> 컬렉션 객체명 = new 컬렉션<객체 종류>();
// Vector<String> v = new Vector(); → v 에 String 객체만 저장 가능
// 생성자() 앞의 <객체 종류> 는 생략 가능

※ Map 인터페이스 구현 클래스들은 키-값 쌍으로 데이터를 관리하기 때문에
2개의 객체 종류 명시 < key 객체 종류1, value 객체 종류2>


< T > Generic 클래스

  • T: 자료형 매개변수(type parameter), 어떤 자료형도 사용할 수 있음을 나타내며
    실제로 사용할 때는 하나의 자료형에 맞춰서 사용할 수 있도록 함
  • T는 컴파일할 때 Object 클래스로 변환됨
  • 클래스 이름을 '클래스명< T >' 로 정의하고 나중에 클래스를 사용할 때
    T 위치에 실제 사용할 자료형을 지정
  • 클래스의 각 메소드에서 해당 자료형이 필요한 부분에 모두 T를 사용하여 구현
  • static 변수와는 함께 사용할 수 없음
    static은 인스턴스의 제너릭 자료형이 결정되기 전에 생성되기 때문에
    static 변수의 자료형이나 static 메소드 내부 변수의 자료형으로는 T 사용 불가

< T > Generic 클래스 구현 형식

// 클래스 정의
class 클래스명<T> {
     // 멤버 변수 선언
    T v[];

    // setter 메소드
    public void setV(T...v){
        this.v = v;
    }

    // getter 메소드
    public T[] getV(){
        return v;
    }
}

※ 멤버 변수와 메소드는 임의로 설정하였으며 자료형 지정을 위와 같은 형식으로 한다는 것


예제

T 자료형 배열에 값을 입력하고 출력하는 프로그램 작성

GenericEX.java

GenericEx 클래스를 담은 파일

package j200210;

public class GenericEx<T> {

    // 멤버 변수
    // String v[]; Double v2[]; Integer v3[];
    T v[];

    // setter, 전달된 인자들이 배열로 변수에 저장됨
    public void setV(T... n) {
        v = n;
    }

    /*
     * public void setV(Double... n) { v2 = n; }
     * 
     * public void setV(Integer... n) { v3 = n; }
     */

    // getter
    public T[] getV() {
        // v[] 출력, 확장 for문
        for (T s : v) {
            System.out.println(s);
        }
        // v[] 반환
        return v;
    }

}

※ 자료형마다 멤버 변수, 메소드를 따로 만들 필요가 없어지고
T(type parameter)로 정의한 뒤에 객체 생성 후 메소드 호출시 자료형에 맞춰 사용


GenericExMain.java

GenericEX 클래스 객체 생성 후 메소드 호출을 위한 파일, main() 포함

package j200210;

public class GenericExMain {

    public static void main(String[] args) {
        // String 자료형만 처리하는 GenericEx 클래스 객체 생성
        GenericEx<String> geStr = new GenericEx();

        // geStr 객체에서 메소드 호출
        geStr.setV("홍길동", "이순신", "세종대왕");
        geStr.getV();

        /*
        홍길동
        이순신
        세종대왕
        */

        // Double형만 처리하는 객체 생성
        GenericEx<Double> geDbl = new GenericEx();
        geDbl.setV(1.2, 2.4, 3.5);
        geDbl.getV();

        /*
        1.2
        2.4
        3.5
        */

        // Integer형만 처리하는 객체 생성
        GenericEx<Integer> geInt = new GenericEx();
        geInt.setV(1, 2, 3);
        geInt.getV();

        /*
        1
        2
        3
        */
    }

}

※ 객체 생성시 자료형을 지정해준 뒤 동일한 메소드를 호출하면 객체의 자료형에 맞게 메소드가 실행됨


제너릭의 개요와 <T>의 사용법에 대해 알아보았습니다.

<T>를 사용하면 여러 자료형을 처리해야하는 클래스를 보다 편리하게 작성할 수 있으면서도

객체 생성시 자료형을 지정하면 일정한 자료형에 대해 클래스 메소드를 호출할 수 있게 되므로

보다 편리하고 유연한 프로그래밍이 가능해진다고 할 수 있겠습니다.