Java - 가변인자, 접근제한자,Getter/Setter

2020. 6. 13. 22:20Java

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
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
 
public class Ex {
 
    public static void main(String[] args) {
        /*
         * Variable Arguments(VARARGS) = 가변 인자 = 비정형 인자 
         * - 메서드 파라미터의 인자가 변하는 형태(갯수의 제한이 없는 인자)
         * - 메서드 선언부의 파라미터 부분에 변수 선언 시 가변인자 기호(...)를 사용하여 표현
         *   => 파라미터의 데이터타입 뒤에 ... 기호를 붙임
         * - 가변인자를 사용하여 메서드를 정의하면 메서드 호출 시 파라미터 갯수에 제한이 없어짐
         *   => 단, 같은 타입의 인자만 전달 가능
         * - 전달받은 데이터는 변수명에 해당하는 1차원 배열로 자동으로 생성됨
         * - 주의! 가변인자는 마지막 파라미터로 단 한 번만 지정 가능
         * 
         * < 기본 문법 >
         * 제한자 리턴타입 메서드명(데이터타입... 변수명) {}
         */
        
        NormalArguments na = new NormalArguments();
        na.normalArguments(12);
        na.normalArguments(123);
//        na.normalArguments(1, 2, 3, 4); // 전달인자 4개를 받는 파라미터 4개 메서드가 없음
        
        System.out.println("-------------");
        
        VariableArguments va = new VariableArguments();
        va.variableArguments(); // 가변인자의 경우 데이터 전달 없이 빈 메서드 호출도 가능
        // 가변인자가 사용된 메서드는 파라미터의 갯수에 제한을 받지 않음
        // => 별도의 오버로딩 없이 여러개의 파라미터를 한꺼번에 처리 가능하게 됨
        va.variableArguments(123);
        va.variableArguments(12345);
        va.variableArguments(12345678910);
        
    }
 
}
 
class NormalArguments {
    // 일반적인 파라미터를 사용할 경우
    public void normalArguments(int a, int b) {
        System.out.println(a + " " + b);
    }
    
    public void normalArguments(int a, int b, int c) {
        System.out.println(a + " " + b + " " + c);
    }
    
}
 
class VariableArguments {
    // 가변인자(비정형인자)를 사용할 경우
    public void variableArguments(int... nums) { 
        // 전달받는 데이터를 갯수에 상관없이 nums 배열로 관리
        // 1. 일반 for문 사용
//        for(int i = 0; i < nums.length; i++) {
//            System.out.print(nums[i] + " ");
//        }
        
        // 2. 확장 for문 사용
        for(int i : nums) {
            System.out.print(i + " ");
        }
        
        System.out.println();
        
    }
}
public class Ex2 {
 
    public static void main(String[] args) {
        /*
         * 접근제한자(Access Modifier = 접근제어자)
         * - 대상에 대한 접근 범위를 제어하는 키워드
         * - 클래스, 메서드, 변수 등에 사용 가능
         * - 종류
         *   1. public - 어디서든(누구나) 접근 가능
         *   2. private - 자신의 클래스 내에서만 접근 가능(다른 클래스에서 접근 불가)
         * 
         * Getter/Setter 메서드
         * - 클래스 내에서 private 접근제한자로 선언된 인스턴스 변수 등에 접근하기 위해
         *   클래스 내에서 제공하는 중개 역할의 메서드
         *   1. Getter : 내부 인스턴스 변수의 값을 외부로 리턴하는 메서드
         *      => getXXX() 형식의 이름을 사용하여 메서드 정의
         *         (XXX 은 접근할 인스턴스 변수의 이름 사용 => ex. 변수명 num = getNum())
         *      => 파라미터는 없고, 리턴값만 있는 메서드 형태로 정의
         *   2. Setter : 외부로부터 값을 전달받아 내부 인스턴스 변수에 저장하는 메서드
         *      => setXXX() 형식의 이름을 사용하여 메서드 정의
         *         (XXX 은 접근할 인스턴스 변수의 이름 사용 => ex. 변수명 num = setNum())
         *      => 파라미터만 있고, 리턴값은 없는 메서드 형태로 정의
         * - 접근제한자는 public 으로 선언
         *   
         */
        // Student 인스턴스 생성
        // id : "20201111", 이름 : "홍길동", 점수 : 80
        Student s = new Student();
        // private 접근제한자가 선언된 인스턴스 변수들은 참조변수를 통해 외부 접근이 불가능
//        s.id = "20201111";
//        s.name = "홍길동";
//        s.score = 80; // The field Student.score is not visible
        // => 클래스 내에서 private 으로 선언된 인스턴스 변수는 외부 접근 불가능(= 보이지 않음)
        
        // Getter/Setter 를 사용하여 인스턴스 변수에 접근하기
        // 1. Setter 를 사용하여 인스턴스 변수 초기화
        s.setId("20201111");
        s.setName("홍길동");
        s.setScore(80);
        
//        System.out.println("id : " + s.id + ", 이름 : " + s.name + ", 점수 : " + s.score);
        
        // 2. Getter 를 사용하여 인스턴스 변수 데이터 출력
        System.out.println(
                "id : " + s.getId() + ", 이름 : " + s.getName() + ", 점수 : " + s.getScore());
        
    }
 
}
 
class Student {
    // 인스턴스 변수에 접근제한자 private 지정 시 다른 클래스에서 접근 불가능
    // => 현재 자신의 클래스(Student) 내에서만 접근 가능함
    private String id;
    private String name;
    private int score;
    
    // 외부에서 접근 불가능한 인스턴스 변수에 대신 접근하는 Getter/Setter 메서드 정의
    // 1. 변수 id 에 대한 Getter/Setter 정의
//    public String getId() {
//        // 인스턴스 변수 id 값을 외부로 리턴
//        return id;
//    }
//    
//    public void setId(String newId) {
//        // 외부로부터 전달받은 id 값을 인스턴스 변수 id 에 저장
//        id = newId;
//    }
//    
//    // 2. 변수 name 에 대한 Getter/Setter 정의
//    public String getName() {
//        return name;
//    }
//    
//    public void setName(String newName) {
//        name = newName;
//    }
//    
//    // 3. 변수 score 에 대한 Getter/Setter 정의
//    public int getScore() {
//        return score;
//    }
//    
//    public void setScore(int newScore) {
//        score = newScore;
//    }
    
    
    // --------------------------------------
    // Getter/Setter 메서드 자동 정의 자동 생성 방법
    // => 클래스 내에 커서를 두고 단축키 Alt + Shift + S -> R 누름
    //    Generate Getters and Setters 창에서 원하는 Getter/Setter 메서드 선택한 뒤 자동 생성
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getScore() {
        return score;
    }
    public void setScore(int score) {
        this.score = score;
    } 
    
    
}
public class Ex3 {
 
    public static void main(String[] args) {
        /*
         * 메서드 호출 시 값 전달 방식에 따른 차이
         * 1. Pass by value(값에 의한 전달)
         *    - 메서드 호출 시 실제값(데이터)을 복사해서 전달 = 기본형 전달
         *    - 호출된 메서드 내에서 전달받은 값을 변경해도 원래 데이터에는 영향이 없음
         *    
         * 2. Pass by reference(참조에 의한 전달)
         *    - 메서드 호출 시 참조값(주소)을 복사해서 전달 = 참조형 전달
         *    - 호출된 메서드 내에서 전달받은 주소값에 접근하여 값을 변경하면
         *      같은 주소를 참조하는 대상은 동일한 영향을 받음
         */
        
        PassByTest pbt = new PassByTest();
        System.out.println("PassByTest 인스턴스의 원본 데이터 : " + pbt.memberVar);
        
        System.out.println("-------------------");
        
        // 1. 메서드 파라미터로 기본형 변수를 전달했을 경우
        System.out.println("change1() 메서드 호출 전 memberVar : " + pbt.memberVar); // 10
        
        // PassByTest 인스턴스 멤버변수(기본형) 값을 change1 메서드에 전달
        pbt.change1(pbt.memberVar); // 기본형 변수값이므로 실제 데이터를 복사해서 전달
        // 호출된 메서드 내에서 전달받은 데이터(복사한 실제 데이터)를 변경하더라도
        // 원본 데이터에는 아무런 영향이 없다!
        System.out.println("change1() 메서드 호출 후 memberVar : " + pbt.memberVar); // 10
        
        System.out.println("=============================================");
        
        // 2. 메서드 파라미터로 참조형 변수를 전달했을 경우
        System.out.println("change2() 메서드 호출 전 memberVar : " + pbt.memberVar); // 10
        
        // PassByTest 인스턴스 주소값(참조형)을 change2 메서드에 전달
        pbt.change2(pbt); // 참조형 변수값이므로 주소값을 복사해서 전달
        // 호출된 메서드 내에서 전달받은 데이터(복사한 주소값)에 접근할 경우
        // 원본 데이터와 동일한 주소값에 접근하므로
        // 한쪽에서 데이터를 변경하게 되면 원본 데이터에 그대로 적용되어 
        // 동일한 주소값을 참조하는 다른 변수에도 영향이 있다!
        System.out.println("change2() 메서드 호출 후 memberVar : " + pbt.memberVar); // 20
        // => change2() 메서드에서 인스턴스의 memberVar 값을 20으로 변경하면
        //    현재 위치에서 pbt 의 memberVar 값도 변경되어 있음
        //    => 변경된 곳의 인스턴스를 공유하므로 동일하게 적용을 받는다!
        
    }
 
}
 
class PassByTest {
    int memberVar = 10;
    
    public void change1(int var) { // 기본형 데이터를 전달받음(복사)
        var += 10// 전달받은 기본형 데이터를 변경
        System.out.println("change1 의 var : " + var);
    }
    
    public void change2(PassByTest reference) {
        // PassByTest 타입 인스턴스의 주소값인 참조형 데이터를 전달받음(복사)
        reference.memberVar += 10// 전달받은 참조형 주소값에 접근하여 데이터를 변경
        System.out.println("change2 의 memberVar : " + reference.memberVar);
    }
    
}
public class Test {
 
    public static void main(String[] args) {
        /*
         * 가변인자를 활용한 계산기
         * - 연산자 1개(char 타입 opr)와 피연산자(정수 x개)를 전달받아
         *   덧셈, 뺄셈, 곱셈, 나눗셈을 처리하는 calc() 메서드 정의
         */
        // Calculator 인스턴스 생성
        Calculator cal = new Calculator();
        
        // 연산자(기호) 1개와 연산에 사용될 피연산자(데이터)를 2 ~ 4개까지 전달하여
        // 해당 연산자에 맞는 연산을 수행하여 결과를 출력
        cal.calc('+'12); // 1 + 2 = 3
        cal.calc('+'123); // 1 + 2 + 3 = 6
        cal.calc('+'1234); // 1 + 2 + 3 + 4 = 10
        
        System.out.println("-----------------------------");
        
        cal.calc('-'102); // 10 - 2 = 8
        cal.calc('-'1023); // 10 - 2 - 3 = 5
        cal.calc('-'10234); // 10 - 2 - 3 - 4 = 1
        
        System.out.println("-----------------------------");
        
        cal.calc('*'12); // 1 * 2 = 2
        cal.calc('*'123); // 1 * 2 * 3 = 6
        cal.calc('*'1234); // 1 * 2 * 3 * 4 = 24
        
        System.out.println("-----------------------------");
        
        cal.calc('/'102); // 10 - 2 = 5
        cal.calc('/'1023); // 10 - 2 - 3 = 1
        
    }
 
}
 
class Calculator {
    
    public void calc(char opr, int...nums) {
        int total = nums[0]; // 첫번째 인자(데이터)를 누적 변수에 저장
        // 첫번째 피연산자를 출력하고 시작
        System.out.print(nums[0]);
        
        if(opr == '+') {
            
            for(int i = 1; i < nums.length; i++) {
                System.out.print(" + " + nums[i]);
                total += nums[i];
            }
            
        } else if(opr == '-') {
            
            for(int i = 1; i < nums.length; i++) {
                System.out.print(" - " + nums[i]);
                total -= nums[i];
            }
            
        } else if(opr == '*') {
            
            for(int i = 1; i < nums.length; i++) {
                System.out.print(" * " + nums[i]);
                total *= nums[i];
            }
            
        } else if(opr == '/') {
            
            for(int i = 1; i < nums.length; i++) {
                System.out.print(" / " + nums[i]);
                total /= nums[i];
            }
            
        }
        
        System.out.println(" = " + total);
        
    }
    
}
public class Test2 {
 
    public static void main(String[] args) {
        /*
         * Account 인스턴스 생성 및 초기화 후 다음과 같이 출력
         * 계좌번호 : 111-1111-111
         * 예금주명 : 홍길동
         * 현재잔고 : 10000원
         */
        
        Account acc = new Account(); // 인스턴스 생성
//        acc.accountNo = "111-1111-111";
//        acc.ownerName = "홍길동";
//        acc.balance = 100000;
        
        // Setter 호출하여 변수 초기화
        acc.setAccountNo("111-1111-111");
        acc.setOwnerName("홍길동");
//        acc.setBalance(100000); // => 대신 deposit() 메서드를 호출하여 입금 기능 사용
        acc.deposit(100000);
        
        // Getter 호출하여 변수값 출력
        System.out.println("계좌번호 : " + acc.getAccountNo());
        System.out.println("예금주명 : " + acc.getOwnerName());
        System.out.println("현재잔고 : " + acc.getBalance());
        
    }
 
}
 
class Account {
    // 계좌번호, 예금주명, 현재잔고 멤버변수를 private 접근제한자로 지정 => Getter/Setter 정의
    private String accountNo; // 계좌번호
    private String ownerName; // 예금주명
    private int balance; // 현재잔고
    
    public String getAccountNo() {
        return accountNo;
    }
    
    public void setAccountNo(String newAccountNo) {
        accountNo = newAccountNo;
    }
    
    public String getOwnerName() {
        return ownerName;
    }
    
    public void setOwnerName(String newOwnerName) {
        ownerName = newOwnerName;
    }
    
    public int getBalance() {
        return balance;
    }
    
    // setBalance() 메서드 대신 deposit() 메서드를 사용하여 입금 처리로 대체 가능
//    public void setBalance(int newBalance) {
//        balance = newBalance;
//    }
    
    // 입금기능
    public void deposit(int amount) {
        balance += amount;
        System.out.println("입금금액 : " + amount + "원");
        System.out.println("현재잔고 : " + balance + "원");
    }
    
}
 
cs

가변 인자와 접근 제한자, Getter/Setter, 메서드 호출 시 값의 전달 방식의 차이에 대해서 배워 보았다. 가변 인자를 배우고 나서야 계산기의 방식이 이해가 갔고 문장도 간단하여 가볍게 배울 수 있었던 거 같다. 접근 제한자 경우에는 일단 두 가지만 배웠다. 항상 쓰던 public과 새롭게 배운 private 였는데 클래스나 메서드, 변수 앞에 써줌으로 인해서 여러 가지 설정을 할 수 있다는 게 새로웠고 private을 쓰며 보안을 걸어둔다는 개념도 이해가 되었다. private를 쓰면 무조건 그쪽으로 접근하기 위해선 Getter/Setter을 써야 한다는 걸 배웠고 Getter/Setter을 쓰기 위한 단축키도 배웠다. Alt + Shift + S = R , 이것인데 그래도 문장을 하나하나 써보며 개념을 이해하는 단계가 필요하다고 생각되었다. Getter는 private 가 걸린 곳에서 값을 불러오는 문장이었고 리턴 값이 있었다. Setter 경우에는 private 이 걸린 곳에 접근하여 값의 초기화를 할 수 있고 리턴 값이 없는 문장이었다. 그리고 메서드 호출 시 값의 전달 방식은 처음엔 무슨 말인가 싶을 정도의 개념이었는데 수업이 끝날 즈음엔 그래도 이해가 되어서 다행이었다. 메서드 호출 시 변수만 입력하여 값을 출력하면 메서드 정의 시에 선언한 변수는 값의 변화가 없이 인스턴스 화가 이루어진 상태에서 불리어진 값에만 변화가 일어나고 메서드 호출 시 인스턴스 화가 이루어진 변수명과 변수가 선언된 곳을 입력하면 클래스 내의 변수도 같이 변화가 이루어진다는 개념이었는데 이해는 갔지만 말로 다시 적으려니 좀 쉽게 적히지 않는다. 좀 더 공부해야겠다.

'Java' 카테고리의 다른 글

Java - this. 문법  (0) 2020.06.14
Java - 생성자, 생성자 오버로딩  (0) 2020.06.13
Java - 메서드 오버로딩  (0) 2020.06.13
Java - 메서드를 활용하기.  (0) 2020.06.13
Java - Class선언, Method() 선언  (0) 2020.06.13