JAVA

Generic(제네릭)

🤖 Play with Android 🤖 2021. 7. 15. 10:04
728x90


Generic(제네릭)을 사용해야 하는 이유

 

제네릭 타입을 사용함으로써 잘못된 타입이 사용될 수 있는 문제를 컴파일 과정에서 미리 제거할 수 있기 때문이다. 자바 컴파일러는 코드에서 잘못 사용된 타입 때문에 발생하는 문제점을 제거하기 위해 제네릭 코드에 대해 강한 타입 체크를 한다. 실행 시 타입 에러가 나는 것보다는 컴파일 시에 미리 타입을 강하게 체크해서 에러를 사전에 방지하는 것이 좋다. 또 부가적인 효과로 제네릭 코드를 사용하면 타입을 국한하기 때문에 요소를 찾아올 때 타입 변환을 할 필요가 없어 프로그램 성능이 향상되는 효과를 얻을 수 있다.

 

 

 

Box클래스

    public class Box {
        private Object obj;
        public void setObj(Object obj){
        this.obj = obj;
        }

        public Object getObj(){
        return obj;
        }
    }

 

BoxExam클래스

public class BoxExam {
        public static void main(String[] args) {
            Box box = new Box();
            box.setObj(new Object());
            Object obj = box.getObj();

            box.setObj("hello");
            String str = (String)box.getObj(); //형변환
            System.out.println(str);

            box.setObj(1);
            int value = (int)box.getObj(); //형변환
            System.out.println(value);
        }
    }

이 코드도 잘못된 코드는 아니다. getObj() 메소드는 파라미터로 Object를 받기 때문에 어떤 데이터 타입도 모두 받을 수 있다. 그러므로 box.getObj부분에 형변환만 잘 시켜주면 어떤 데이터 타입이든 저장할 수 있다.

 

하지만 만약 다른 데이터 타입을 setObj() 메소드 부분에 넣어준다면 컴파일은 되지만 실행하면 런타임에 오류가 나는 것을 확인할 수 있다.

 

 

 Generic이라는 사용됨으로써 인스턴스를 만들때 사용하는 타입을 지정

 

 

Generic을 이용하여 Box 클래스 수정

   public class Box<E> {
        private E obj;
        public void setObj(E obj){
            this.obj = obj;
        }

        public E getObj(){
            return obj;
        }
    }
  • 클래스 이름 뒤에 <E>가 제네릭을 적용한 것이다. Box는 가상의 클래스 E를 사용한다는 의미.
  • Object를 받아들이고, 리턴하던 부분이 E로 변경. E는 실제로 존재하는 클래스는 아니다.

 

Generic을 이용하여 수정한 Box를 이용하는 BoxExam클래스

  public class BoxExam {
        public static void main(String[] args) {
            Box<Object> box = new Box<>();
            box.setObj(new Object());
            Object obj = box.getObj();

            Box<String> box2 = new Box<>();
            box2.setObj("hello");  //만약 다른 데이터타입을 넣으면 오류
            String str = box2.getObj();
            System.out.println(str);

            Box<Integer> box3 = new Box<>();
            box3.setObj(1);  //만약 다른 데이터타입을 넣으면 오류
            int value = (int)box3.getObj();
            System.out.println(value);
        }
    }

 

  • 참조 타입에<Object> , <String>, <Integer>가 있는 것을 볼 수 있다.
  • 첫 번째는 Object를 사용하는 Box를 인스턴스로 만들겠다는 의미
  • 두 번째는 String을 사용하는 Box인스턴스를 만들겠다는 의미
  • 세 번째는 Integer를 사용하는 Box인스턴스를 만든다는 의미

 

* 자바에서 타입 변수 자리에 사용할 실제 타입을 명시할 때 기본 타입을 바로 사용할 수는 없다.
이때는 위 예제의 Integer와 같이 래퍼(wrapper) 클래스를 사용해야만 한다.

 

 

 

 

 

또한, Java SE 7부터 인스턴스 생성 시 타입을 추정할 수 있는 경우에는 타입을 생략할 수 있다.

MyArray<Integer> myArr = new MyArray<>(); // Java SE 7부터 가능함.