본문 바로가기

Java

[Andoird] Generic (In Java)

#What 

API 문서들을 보면 Generic 표현이 널려있는 것을 볼 수 있습니다.

보다 정확한 도큐먼트 이해를 위해 Generic 표현을 정리해 봅시다.

 

Generic이란? 

  • 클래스, 인터페이스, 메소드 내부에서 사용할 데이터 타입을 외부에서 지정해서 사용 하는 방법
  • 사전적 의미 : <포괄적인, 총칭[통칭]의>

 

장점

  • Casting, 즉 타입 변환 할 필요 없음 (불필요한 성능 소모X)
  • 컴파일 시 잘못된 타입 사용에 대한 체크가 가능(타입 제한이 되므로)

 

#예제 1 - 어떻게 사용하는가?

JAVA

Kotlin

 

 

#예제 2  -  클래스에 Generic 적용 하기

Student 클래스에 'id'필드의 타입을 int, String 등 2가지 이상의 타입으로 받고 싶을 경우

 

Generic 사용 X 

    public class Student {
        private Object id;

        public Object getId() {
            return id;
        }

        public void setId(Object id) {
            this.id = id;
        }
    }

    public void genericTest() {
        Student student = new Student();
        student.setId(1);//형변환
        int idInt = (int) student.getId(); //형변환

        Student student2 = new Student();
        student2.setId("1"); //형변환
        String idStr = (String) student2.getId(); // 형변환
    }

generic을 사용하지 않을 경우 set 할 때도( 타입 -> Object), get 할 때도(Object -> 타입 ) 타입변환이 일어난다.

casting의 불편함을 떠나서 퍼포먼스적으로도 좋지 못하다.

 

 

Generic 사용 O

    public class Student<T> {
        private T id;

        public T getId() {
            return id;
        }

        public void setId(T id) {
            this.id = id;
        }
    }

    public void genericTest() {
        Student<Integer> student = new Student<>();
        student.setId(1);
        int idInt = student.getId();

        Student<String> student2 = new Student();
        student2.setId("1");
        String idStr = student2.getId();
    }

규칙 : 클래스 선언 뒤에  '타입 파라미터'를 명시 <T>

generic을 사용하게 된다면 set/get 시 타입 변환 없이 사용할 수 있다

 

*이 처럼 타입을(<T>) 파라미터로 가지는 클래스와 인터페이스를 '제네릭 타입' 이라고 한다

 

 

#예제 3  -  함수의 파라미터와 리턴 타입에 Generic 적용 하기

배열로 인자들을 받아서 LIST로 변환 해주는 함수... 예제를 위한 예제를 보자

    //리턴 타입 = List<K>
    //파람 타입 = K
    public <K> List<K> getArrayList(K... element) {
        List<K> list = new ArrayList<>(Arrays.asList(element));
        return list;
    }

    public void genericTest() {
        List<String> listStr = getArrayList("element1","element2","element3");
        List<Integer> listInt = getArrayList(1,2,3);
    }

 

규칙 :  리턴 타입 앞에 '타입 파라미터'를 명시 <K>  

getArrayList() 함수의 리턴타입은 'List<K>' 이고 파라미터 타입은 'K' 이다

*이 처럼 타입을(<T>) 파라미터나 리턴에 사용하는 메소드를 '제네릭 메소드' 라고 한다

 

 

#예제 4  -  타입을 제한하고 싶을 때

타입을 외부에서 정하고 자유롭게 사용할 수 있는게 Generic이지만 필요한경우 타입을 제한 할 수 있다

<T extends 최상위타입> 형태로 사용한다.

 

Number 타입으로 제한된 Prameter만 전달 받아서, 더하기 후 Double 형태로 반환 하는 예제 

"1","2" String은 Number 타입이 아니므로 사용할 수 없는 것을 볼 수 있다.

    public <T extends Number> Double add(T param1, T param2) {
        double value1 = param1.doubleValue();
        double value2 = param2.doubleValue();
        return value1 + value2;
    }

    public  void test() {
       // Double result  = add("1","2");//String은 Number 타입이 아니므로, 컴파일 에러
        Double result01  = add(1,2);
        Double result02  = add(1.0,2.0);
    }

 

 

#예제 5  -  Generic 상속

Generic을 사용하는 클래스/인터페이스도 부모 클래스가 될 수 있고, 상속이 가능하다

Student<T> 클래스를 부모로 하는 HighSchoolStudent<T,C> 클래스로 확인해 보자


public class Student<T> {
    private T id;

    public T getId() {
        return id;
    }

    public void setId(T id) {
        this.id = id;
    }
}

public class HighSchoolStudent<T, C> extends Student<T> {
    private C name;
 
    public C getName() {
        return name;
    }

    public void setName(C name) {
        this.name = name;
    }
}

public void test() {
    HighSchoolStudent<Integer, String> highSchoolStudent = new HighSchoolStudent();
    highSchoolStudent.setId(1);
    highSchoolStudent.setName("Tina");
}

 


 

문제 있을시 알려 주세요.

 

좋은 하루 되세요!

'Java' 카테고리의 다른 글

[JAVA] 추상클래스/인터페이스 (+Kotlin)  (1) 2021.12.16