Java - Generic

2020. 6. 30. 23:30Java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
package generic;
 
public class Ex {
 
    public static void main(String[] args) {
        
        /*
         * 제네릭(Generic)
         * 미리 사용할 타입을 결정한 뒤, 컴파일 시점에 사용될 데이터 타입을 체크하는것
         * 클래스 정의 시 클래스명 뒤에 <>기호 사이에 가상의 임시 자료형을 지정
         * 보통 영문 대문자 1글자 지정
         * 지정된 타입은 클래스 내에서 임시 데이터타입으로 사용되며
         * 인스턴스 생성 시점에서 특정 데이터타입을 지정하여 해당 타입으로 교체
         * 제네릭 타입 지정시 반드시 클래스 타입만 지정 가능함
         * 코드의 안정성이 향상되며, 형변환 연산자 등을 생략할 수 있으므로 코드가 절감됨.
         * 
         */
        //Object 타입 변수에 데이터를 저장할 경우 모든 타입 저장이 가능하므로
        //데이터 저장 시 매우 편리하나, 데이터를 사용할 때 문제가 발생할 수 있다.
        Object o= 10;
        int num=(int)o;
        System.out.println(num+10);
        
        o="abc";
//        num=(int)o;//String ->int(Integer)로 변환이 불가능하므로 오류 발생!@#!#@$%$^&*
//        //다만, 문법적 오류가 없으므로 컴파일 시점이 아닌 실행 시점에 오류 발견됨
        
        
        //사용 전 기본 데이터타입이 아닌 Wrapper 클래스타입을 사용하여 타입체크후 사용
        if(o instanceof Integer) {
            //Integer 타입(int) 이 아닌 경우 내부코드 실행 X
            num=(int)o;//String ->int(Integer)로 변환이 불가능하므로 오류 발생!@#!#@$%$^&*
            //다만, 문법적 오류가 없으므로 컴파일 시점이 아닌 실행 시점에 오류 발견됨
            System.out.println(num+10);
        }
        
        
        
        
        System.out.println("--------------------------");
        NormalBox nb=new NormalBox();
        
        //Setter의 파라미터가 Object 타입이므로 Toy, Grocery 객체 등 모든 타입 전달 가능
        nb.setSome(new Toy());
        nb.setSome(new Grocery());
        
        //Getter 의 리턴타입이 Object 타입이므로 모든 타입을 Object로 리턴 가능
        Object some=nb.getSome();
        
//        Toy toy=some;//Object->Toy  변환 시 다운캐스팅 필요
//        Toy toy=(Toy)some;//다운캐스팅(문법적 오류 해결)
        //코드 실행 시점에서 변환 과정 문제가 발견됨
        
        //형변환 과정에서 문제 발생을 차단하기 위해서는 변환 전 타입 체크 필요= instanceof
        
        if(some instanceof Toy) {
            Toy toy=(Toy)some;
            System.out.println("Object->Toy로 다운캐스팅");
        }else if(some instanceof Grocery) {
            Grocery gr=(Grocery)some;
            System.out.println("Object->Grocery로 다운캐스팅");
        }
        System.out.println("---------------------------------");
        
        //제네릭으로 정의된 클래스 사용
        //GenericBox 인스턴스 생성 시 제네릭 타입을 Toy 타입으로 거정
        //클래스 내의 가상의 자료형 T-> Toy로 모두 변경됨
        GenericBox<Toy> gb1=new GenericBox<Toy>();
        gb1.setSome(new Toy());//Setter 메서드 파라미터가 T->Toy로 변경되어 있음
//        gb1.setSome(new Grocery());//컴파일 에러 발생! Toy 타입 외의 객체 전달 불가
        //제네릭을 적용하면 오류를 발견하는 시점이 컴파일(번역) 시점이 된다.
        //코드의 안정성 향상!됨!@$@$#$^#$%^$%
        
        
        //Getter 메서드 리턴타입이 Toy 로 바뀌었으므로
        //타입체크 (instanceof) 나 형변환 연산자가 필요없음!@#!@#%ㅆ$^%&^@
        Toy toy=gb1.getSome();
        
        GenericBox<Grocery> gb2=new GenericBox<Grocery>();
//        gb2.setSome(new Toy());//Setter 메서드 파라미터가 T->Grocery로 변경되어 있음
        gb2.setSome(new Grocery());//컴파일 에러 발생! Grocery 타입 외의 객체 전달 불가
        
        //Getter 메서드 리턴타입이 Grocery로 바뀌었으므로
        //타입체크(instanceof)나 형변환 연산자가 필요없음(코드절감)
        Grocery g=gb2.getSome();
        
        GenericBox gb3=new GenericBox();
        
        //제네릭 타입 지정 생략할 경우 <T> -> Object 로 변경됨
        gb3.setSome(new Toy());
        gb3.setSome(new Grocery());
        
        System.out.println("-----------------------------");
        
//        GenericBox<int> gb4=new GenericBox<int>();//제네릭 타입은 기본형 지정 불가
        GenericBox<Integer> gb4=new GenericBox<Integer>();
        gb4.setSome(1);
        
        GenericBox<String> gb5=new GenericBox<String>();
        gb5.setSome("1");
        
        System.out.println("------------------------------");
        
        
        
    }
 
}
 
class Toy{}
class Grocery{}
class NormalBox{
    //Object 타입으로 변수를 선언하면 모든 데이터타입을 전달받을 수 있어 저장 시 편리함 
    private Object some;
 
    public Object getSome() {
        return some;
    }
 
    public void setSome(Object some) {
        this.some = some;
    }    
}
//제네릭을 적용한 GEnericBox클래스 정의
//클래스명 뒤에 <> 기호를 쓰고, 사이에 영문 대문자 1글자 지정
//이때, 지정한 영문 대문자는 클래스 내에서 임시 데이터타입으로 사용 가능
//(클래스 내에서만 유효한 가상의 임시 데이터타입)
//클래스 정의 시점에서는 어떤 데이터타입이 될지 알 수 없음
//인스턴스 생성 시점에 데이터타입을 명시하게 됨.(해당 데이터타입으로 교체됨)
class GenericBox<T>{
    private T some;
 
    public T getSome() {
        return some;
    }
 
    public void setSome(T some) {
        this.some = some;
    }    
}
 
package generic;
 
import java.util.ArrayList;
 
public class Ex2 {
 
    public static void main(String[] args) {
        
        /*
         * 제네릭을 적용한 자바의 API
         * 컬렉션 프레임워크 등에서 기본적으로 제네릭을 적용하여 클래스를 정의
         * ArrayList, HashSet, HashMap 등에 제네릭 사용 가능
         * 
         */
        
        
        ArrayList<Integer> list= new ArrayList<Integer>();
        list.add(1);
//        list.add(3.14);//컴파일 오류!(Integer 타입 필수)
        
        ArrayList<Double> list1=new ArrayList<Double>();
//        list1.add(1);//컴파일 오류!@#(Double 타입 필수)
        list1.add(3.14);
        
        //---------------------------------------------
        
        //DB작업에 사용되는 DTO 클래스(자바빈 객체)도 제네릭 타입으로 지정 가능
        ArrayList<BoardDTO> boardlist=new ArrayList<BoardDTO>();
        
        BoardDTO dto=new BoardDTO(1"게시물 제목""게시물 내용");
        boardlist.add(dto);
        
//        MemberDTO dto2=new MemberDTO();
//        boardlist.add(dto2);// BoardDTO 객체 외의 나머지 전달 불가
        
        BoardDTO dto3=new BoardDTO(2"게시물 제목2""게시물 내용2");
        boardlist.add(dto3);
        
        //ArrayList 객체에 저장된 BoardDTO 객체 꺼내서 메서드 호출
        for(BoardDTO board:boardlist) {
            System.out.println(board.getTitle()+", "+board.getContent());
        }
        
        for(int i=0;i<boardlist.size();i++) {
            BoardDTO board=boardlist.get(i);
            //BoardDTO 타입으로 꺼내올 떄 타입 판별이나 형변환 등 필요없음.
            System.out.println(board.getTitle()+", "+board.getContent());
        }
        
        
    }
 
}
class MemberDTO{}
class BoardDTO{
    int idx;
    String title;
    String content;
    public BoardDTO(int idx, String title, String content) {
        super();
        this.idx = idx;
        this.title = title;
        this.content = content;
    }
    public int getIdx() {
        return idx;
    }
    public void setIdx(int idx) {
        this.idx = idx;
    }
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public String getContent() {
        return content;
    }
    public void setContent(String content) {
        this.content = content;
    }
    
    
    
    
}
cs

Generic을 배워보았는데 

클래스를 정의 할때 어떤 타입을 쓸 건지 미리 정할 필요가 있을 때 <>를 사용하여

영문 대문자 한글자를 사용하여 임시로 데이터 타입을 표시한 후 나중에 객체 생성을 할 때 사용할 데이터 타입을

표시해 주는 방식이다. 대신에 클래스 타입만 사용 가능하기 때문에  int 등 사용은 불가능하고 Integer 등 참조 데이터 타입을 사용하여야 한다. 코드 생성 시 코드 절감이 이루어지고 형 변환 연산자 등을 미리 사용할 필요가 없기 때문에 안정성이 크게 이루어진다. 아주 자주 쓰이게 될 테니 잘 기억해 두어야겠다!

'Java' 카테고리의 다른 글

Java- enum  (0) 2020.07.01
Java - Date,time,Calendar  (0) 2020.06.30
Java - Stack & Queue  (0) 2020.06.30
Java - Collection 프레임워크의 Map  (0) 2020.06.30
Java - BigInteger,BigDecimal  (0) 2020.06.30