언어 자료구조 알고리즘/디딤돌 Java 언어 Part2 활용

[Java 언어 활용] 3.1 제네릭(Generic)

언제나휴일 2016. 12. 10. 00:18
반응형

[Java 언어 활용] 3.1 제네릭(Generic)


 제네릭(Generic)은 여러 형식에 맞게 재사용할 수 있는 코드를 정의하는 기술을 말합니다. 제네릭 코드를 정의할 때는 가상의 형식 이름을 <가상 형식 이름> 처럼 정의하고 사용하는 곳에서 어떠한 형식에 관한 코드를 사용할 것인지 명시하여 사용하는 기법입니다.

 

 먼저 제네릭 클래스를 정의할 때는 클래스명 뒤에 <가상 형식 이름>을 명시하여 만들 수 있습니다.

class 클래스명<가상 형식 이름>{

}

 

 사용하는 곳에서는 가상 형식 이름 대신 구체적으로 사용할 형식을 결정하여 <사용할 형식 이름>을 명시하여 사용합니다.

클래스명<사용할 형식 이름> 변수명 = new 클래스명<사용할 형식 이름>();

 

 다음은 정수 형식을 보관하는 정수 적 배열 클래스와 제네릭 형식으로 원하는 형식을 사용자가 결정할 수 있는 제네릭 동적 배열 클래스를 정의한 것입니다.

 

▷ 소스 3.1 정수 동적 배열과 제네릭 동적 배열 예

//IntDArray.java

//정수 동적 배열

public class IntDArray {

        int[] buffer;

        int capacity;

        int usage;

        public IntDArray(int capacity){

               this.capacity = capacity;

               buffer = new int[capacity];

               usage = 0;

        }      

        public boolean isEmpty(){

               return usage == 0;

        }

        public boolean isFull(){

               return usage == capacity;

        }

        public int size(){

               return usage;

        }

        public boolean add(int value){

               if(isFull()){

                       return false;

               }                     

               buffer[usage] = value;

               usage++;

               return true;

        }

        public void viewAll(){

               String outstr = String.format("저장소 크기:%d 보관개수:%d",capacity,usage);

               System.out.println(outstr);

               for(int i = 0; i<usage;i++){

                       System.out.print(buffer[i]+" ");

               }

               System.out.println();

        }

}

//DArray.java

//제네릭 동적 배열

public class DArray<datatype> {

        Object[] buffer;

        int capacity;

        int usage;

        public DArray(int capacity){

               this.capacity = capacity;             

               buffer = new Object[capacity];

               usage = 0;

        }      

        public boolean isEmpty(){

               return usage == 0;

        }

        public boolean isFull(){

               return usage == capacity;

        }

        public int size(){

               return usage;

        }

        public boolean add(datatype value){

               if(isFull()){

                       return false;

               }                     

               buffer[usage] = value;

               usage++;

               return true;

        }

        public void viewAll(){

               String outstr = String.format("저장소 크기:%d 보관개수:%d",capacity,usage);

               System.out.println(outstr);

               for(int i = 0; i<usage;i++){

                       System.out.print(buffer[i]+" ");

               }

               System.out.println();

        }

}

//Program.java

//정수 동적 배열과 제네릭 동적 배열

public class Program {

        public static void main(String[] args){

               System.out.println("==Test IntDArray===");

               IntDArray idarr = new IntDArray(10);

               idarr.viewAll();

               idarr.add(3);

               idarr.viewAll();

               idarr.add(2);

               idarr.viewAll();

               idarr.add(6);

               idarr.viewAll();

              

               System.out.println("==Test DArray<integer>===");

               DArray<Integer> darr = new DArray<Integer>(10);

               darr.viewAll();

               darr.add(3);

               darr.viewAll();

               darr.add(2);

               darr.viewAll();

               darr.add(6);

               darr.viewAll();

              

               System.out.println("==Test DArray<String>===");

               DArray<String> darr2 = new DArray<String>(10);

               darr2.viewAll();

               darr2.add("Hello");

               darr2.viewAll();

               darr2.add("언제나 휴일");

               darr2.viewAll();

               darr2.add("ehpub.co.kr");

               darr2.viewAll();

        }

}

 

▷ 소스 3.1 실행 결과

==Test IntDArray===

저장소 크기:10 보관개수:0

 

저장소 크기:10 보관개수:1

3

저장소 크기:10 보관개수:2

3 2

저장소 크기:10 보관개수:3

3 2 6

==Test DArray<integer>===

저장소 크기:10 보관개수:0

 

저장소 크기:10 보관개수:1

3

저장소 크기:10 보관개수:2

3 2

저장소 크기:10 보관개수:3

3 2 6

==Test DArray<String>===

저장소 크기:10 보관개수:0

 

저장소 크기:10 보관개수:1

Hello

저장소 크기:10 보관개수:2

Hello 언제나 휴일

저장소 크기:10 보관개수:3

Hello 언제나 휴일 ehpub.co.kr

 

 

 또한 메소드의 특정 인자 형식을 제네릭 형태로 표현할 수도 있습니다. 이 때 메소드 리턴 형식 이름 앞에 <가상 형식 이름>으로 명시하여 작성합니다. 이러한 메서드를 제네릭 메서드라 부르며 호출하는 곳에서는 실제 값 형식을 알고 있기 때문에 형식 이름을 명시할 필요가 없습니다.

 

 다음은 제네릭 메서드를 정의하여 사용한 예입니다. 여기서 제네릭 메서드는 전달받은 값을 출력한 후에 다시 그 값을 반환하는 메서드로 큰 의미는 없습니다. 단지 제네릭 메서드를 보여주기 위함입니다.

 

▷ 소스 3.2 제네릭 메서드

//제네릭 메서드

public class Program {

        static <T> T Foo(T value){

               System.out.print(value);

               System.out.println();

               return value;          

        }

        public static void main(String[] args){

                int i = 10;

               int re = Foo(i);

               System.out.println("re:"+re);

        }

}

 

▷ 소스 3.2 실행 결과

10

re:10

 

 제네릭을 표현할 때 특정한 규약을 따르는 형식만 사용할 때도 있습니다. 만약 정렬 메서드를 제공하려면 개체의 값을 비교할 수 있어야 할 것입니다. Java 라이브러리에는 Comparable 인터페이스를 정의하고 있고 비교할 수 있는 형식을 정의할 때 Comparable 인터페이스를 기반으로 구현 클래스를 정의하는 것을 권장합니다. 따라서 정렬 메서드를 제공할 때 최소한 Comparable 인터페이스를 기반의 구현 클래스로 한정할 필요가 있습니다. 주의할 점은 인터페이스일 때도 <가상 형식 이름 extends 특정 형식 이름> 형태로 표현해야 합니다.

 

 다음은 정적 메서드 Sort의 입력 매개 변수로 Comparable 인터페이스로 한정한 제네릭 메서드를 구현한 예제입니다.

 

▷ 소스 3.3 Comparable 인터페이스로 한정한 제네릭 메서드 Sort

//Comparable 인터페이스로 한정한 제네릭 메서드 Sort

public class Program {

        static <dt extends Comparable> void Sort(dt[] arr){

              

               for(int i = arr.length; i>1; i--){

                       for(int j=1; j<i;j++){

                              if(arr[j].compareTo(arr[j-1])<0){

                                      dt temp = arr[j-1];

                                       arr[j-1] = arr[j];

                                      arr[j] = temp;

                              }

                       }

               }

        }

        public static void main(String[] args){

               String[] arr = {"홍길동", "강감찬", "을지문덕", "김구", "이순신"};

               System.out.println("정렬 ");

               for(int i = 0; i<arr.length;i++){

                       System.out.print(arr[i]+" ");

                }

               System.out.println();

              

               Sort(arr);            

              

               System.out.println("정렬 ");

               for(int i = 0; i<arr.length;i++){

                       System.out.print(arr[i]+" ");

               }

               System.out.println();

        }

}

 

▷ 소스 3.3 실행 결과

정렬

홍길동 강감찬 을지문덕 김구 이순신

정렬

강감찬 김구 을지문덕 이순신 홍길동

 

반응형