[ CH03. 반복문과 배열 그리고 예외 처리 ]
1. 반복문
- 문장 또는 문장들을 반복해서 수행할 때 사용
- 반복 횟수가 중요한 경우 → for문, 그 외의 경우 → while문
1.1 for 문
- 구성
- 초기화, 조건식, 반복 후 작업 그리고 수행할 블록 또는 문장으로 구성
- 특이한 형태
// 반복 조건이 true이면 무한 반복
for(초기작업; true; 반복후작업) {
}
// 반복조건이 비어 있으면 true로 간주, 무한 반복
for(초기작업; ; 반복후작업) {
}
// 초기 작업과 반복후작업은 ‘,’로 분리하여 여러 문장 나열 가능
for(i=0; i<10; i++, System.out.println(i)) {
}
// for문 내에 변수 선언
for(int i=0; i<10; i++) { // 변수 i는 for문 내에서만 사용 가능
}
- 향상된 for문
- 타입은 배열 또는 컬렉션의 요소의 타입이어야 함
- 배열 또는 컬렉션에 저장된 값이 매 반복마다 하나씩 순서대로 읽혀서 변수에 저장
// 향상된 for문의 구성
for( 타입 변수명 : 배열 또는 컬렉션 ) {
// 반복할 문장
}
int[] arr = {10,20,30,40,50};
for(int tmp: arr) {
System.out.print(tmp + " ");
}
// [출력]
10 20 30 40 50
- 예제
package day03;
public class ForSample {
public static void main(String[] args) {
int sum = 0;
for(int i =1; i<= 10; i++) {
sum+= i;
System.out.print(i);
if(i <= 9)
System.out.print("+");
else {
System.out.print("=");
System.out.println(sum);
}
}
}
}
1.2 while 문
- 구성
- 조건식과 수행할 블록 또는 문장으로 구성
- 조건식 생략 불가!!
- 반복 조건이 true이면 반복, false이면 반복 종료
- 반복 조건이 없으면, 컴파일 오류
- 처음부터 반복 조건을 통과한 후 작업문 수행
- 중첩 가능하며, 중첩횟수 제한 X
- 예제
package day03;
import java.util.Scanner;
public class WhileSample {
public static void main(String[] args) {
int count = 0;
int sum = 0;
Scanner sc = new Scanner(System.in);
System.out.println("정수를 입력하고 마지막에 -1을 입력하세요.");
int n = sc.nextInt(); // 정수 입력
while(n != -1) { // -1이 입력되면 while문 벗어남
sum += n;
count++;
n = sc.nextInt();
}
if(count == 0) System.out.println("입력된 수가 없습니다.");
else {
System.out.print("정수의 개수는 " + count + "개이며, ");
System.out.println("평균은 " + (double)sum/count + "입니다.");
}
sc.close();
}
}
1.3 do-while 문
- 구성
- 무조건 최소 한번 작업문 실행
- 반복 조건이 true이면 반복, false이면 반복 종료
- 반복 조건이 없으면 컴파일 오류
- 예제
package day03;
public class DoWhileSample {
public static void main(String[] args) {
char c = 'a';
do {
System.out.print(c);
c = (char)(c+1); // 문자는 더하면 다음 순서 알파벳이 나옴
}
while(c <= 'z');
}
}
1.4 중첩 반복
- 반복문이 다른 반복문을 내포하는 구조
- 중첩 횟수 제한 X
- 너무 많은 중첩 반복은 프로그램 구조를 복잡하게 하므로, 2중 3중 반복이 적당
package day03;
public class NestedLoop {
public static void main(String[] args) {
for(int i=1; i<10; i++) {
for(int j=1; j<10; j++) {
System.out.print(i+ "*" + j + "=" + i*j);
System.out.print('\t');
}
System.out.println();
}
}
}
1.5 continue 문
- 반복문을 빠져 나가지 않으면서 다음 반복으로 진행
- continue문 이후의 문장들 수행 X
1.6 break 문
- 반복문 하나를 완전히 빠져나갈 때 사용
- 중첩 반복의 경우 안쪽 반복문의 break문이 실행되면, 안쪽 반복문만 벗어남
1.7 이름 붙은 반복문과 break, continue
- 반복문 앞에 이름 붙이고, 그 이름을 break, continue와 같이 사용함으로써 둘 이상의 반복문을 벗어나거나 반복을 건너뛰는 것 가능
2. 배열
2.1 1차원 배열
- 정의
- 인덱스와 인덱스에 대응하는 데이터들로 이루어진 자료구조
- 한 번에 많은 메모리 공간 할당 가능
- 같은 타입의 데이터들이 순차적으로 저장(연속적)
- 인덱스를 이용하여 원소 데이터 접근
- 반복문을 이용하여 처리하기에 적합
- 배열 인덱스
- 0부터 시작
- 인덱스 : 배열의 시작 위치에서부터 데이터가 있는 상대 위치
- 배열 선언
int intArray[];
char charArray[];
int[] intArray[];
char[] Array[];
- 배열 생성
intArray = new int[10];
charArray = new char[20];
int intArray[] = new int[10];
char charArray[] = new char[20];
- 배열 초기화
// 올바른 초기화 방법
int intArray[] = {0,2,3,4};
// 잘못된 배열 선언
int intArray[10]; // 오류: 배열의 크기를 지정하면 안됨
- 배열 원소 접근
- [] 사이에 원소의 인덱스를 적어 접근
- 배열의 시작 인덱스 = 0
- 배열의 마지막 인덱스 = (배열 크기 - 1)
- 반드시 배열 생성 후 접근해야 함
int intArray [] = new int[5]; // 원소가 5개인 배열 생성. 인덱스는 0~4까지 가능
intArray[0] = 5; // 원소 0에 5 저장
intArray[3] = 6; // 원소 3에 6 저장
int n = intArray[3]; // 원소 3의 값을 읽어 n에 저장. n은 6이 됨
// 오류: 배열 생성하지 않고 접근
int intArray2[];
intArray2[1] = 8; // 생성되지 않은 배열
- 레퍼런스 치환과 배열 공유
- 하나의 배열을 다수의 레퍼런스가 참조 가능
- 배열의 크기: length 필드
- 배열 객체 내에 length 필드는 배열의 크기 나타냄
- 배열은 자바에서 객체로 관리
int intArray[] = new int[5];
int size = intArray.length // size = 5
- 배열에서의 for-each 문
- 배열이나 나열(enumeration)의 각 원소를 순차적으로 접근하는데 유용한 for문
package day03;
public class ForeachEx {
enum Week{월, 화, 수, 목, 금, 토, 일}
public static void main(String[] args) {
int[] n= {1,2,3,4,5};
String names[] = {"사과", "배", "바나나", "체리", "딸기", "포도"};
int sum = 0;
for(int k:n) {
System.out.print(k + " ");
sum += k;
}
System.out.println("합은 " + sum);
for(String s: names)
System.out.print(s + " ");
System.out.println();
for(Week day: Week.values())
System.out.print(day + "요일");
System.out.println();
}
}
2.2 배열의 복사
- for문을 이용한 배열 복사
int[] number = {1,2,3,4,5};
int[] newNumber = new int[10];
for(int i=0; i<number.length; i++) {
newNumber[i] = number[i]; // number의 값 newNumber에 저장
}
- System.arraycopy()를 이용한 배열 복사
- for문을 이용한 배열 복사보다 효율적
2.3 2차원 배열
- 선언, 생성, 초기화
// 2차원 배열 선언
int intArray[][];
char charArray[][];
int[][] intArray;
char[][] charArray;
// 2차원 배열 생성
intArray = new int[2][5];
charArray = new char[5][5];
int intArray[] = new int[2][5];
char charArray[] = new char[5][5];
// 2차원 배열 초기화
int intArray[][] = {{0,1,2},{3,4,5},{6,7,8}};
char charArray[][] = {{'a', 'b', 'c'},{'d‘, 'e', 'f'}};
double doubleArray[][] = {{0.01, 0.02}, {0.03, 0.04}};
- 2차원 배열의 크기
- i.length : 2원 배열의 행의 개수
- i[n].length : n번째 행의 열의 개수
2.4 비정방형 배열
- 정방형 배열
- 각 행의 열의 개수가 같은 배열
- 비정방형 배열(가변 배열)
- 각 행의 열의 개수가 다른 배열
package day03;
public class SkewedArray {
public static void main(String[] args) {
int intArray[][] = new int[4][]; // 각 행의 레퍼런스 배열 생성
intArray[0] = new int[3]; // 첫째 행의 정수 3개의 배열 생성
intArray[1] = new int[2]; // 둘째 행의 정수 3개의 배열 생성
intArray[2] = new int[3]; // 셋째 행의 정수 3개의 배열 생성
intArray[3] = new int[2]; // 넷째 행의 정수 3개의 배열 생성
for (int i=0; i<intArray.length; i++) // 행에 대한 반복
for(int j=0; j<intArray[i].length; j++) // 열에 대한 반복
intArray[i][j] = (i+1) *10 + j;
for (int i=0; i<intArray.length; i++) { // 행에 대한 반복
for(int j=0; j<intArray[i].length; j++) // 열에 대한 반복
System.out.print(intArray[i][j] + " ");
System.out.println();
}
}
}
2.5 메서드에서의 배열 리턴
- 배열의 레퍼런스를 리턴
- 메서드의 리턴 타입
- 메소드의 리턴 타입과 리턴 받는 배열 타입이 일치해야 함
- 리턴 타입에 배열의 크기를 지정하지 않음
package day03;
public class ReturnArray {
static int[] makeArray() { // 정수형 배열을 리턴하는 메소드
int temp[] = new int[4]; // 배열 생성
for(int i=0; i<temp.length; i++)
temp[i] = i; // 배열의 원소를 0,1,2,3 으로 초기화
return temp; // 배열 리턴
}
public static void main(String[] args) {
int intArray[] = makeArray(); // 배열 레퍼런스 변수에 메소드로 부터 배열 전달 받음
for(int i=0; i<intArray.length; i++)
System.out.print(intArray[i] + " "); // 배열 모든 원소 출력
}
}
// [출력]
0 1 2 3
2.6 String 배열
- 선언과 생성
- 배열의 각 요소의 값은 참조형 변수의 기본값 null로 초기화
String[] name = new String[3]; // 3개의 문자열을 담을 수 있는 배열 생성
- 초기화
- 배열의 각 요소에 문자열 지정
- 원래 클래스는 new연산자를 통해 객체를 생성해야 하지만,
String 클래스는 특별히 큰 따옴표만으로 간략히 표현 가능
- 참조형 배열(객체 배열)은 실제 객체가 아닌 각 객체의 주소 값이 저장
// 초기화 방법 1
String[] name = new String[2];
name[0] = new String("kim");
name[1] = new String("park");
// 초기화 방법 2
String[] name = new String[2];
name[0] = "kim";
name[1] = "park";
// 초기화 방법 3
String[] name = new String[]{"kim", "park"};
// 초기화 방법 4
String[] name = {"kim", "park"};
- String 객체(문자열) 특징
- 읽기 O, 내용 변경 X
// 내용 변경 X → 새로운 내용의 문자열이 생성된 것
String str = "java";
str = str + 8; // "java8"이라는 새로운 문자열이 str에 저장
System.out.println(str); // "java8"
- char 배열과 String 클래스의 변환
char[] chArr = {'A','B','C','D'};
String str = new String(chArr); // char 배열 → String
char[] tmp = str.toCharArray(); // String → char 배열
// [결과]
str = "abcd"
tmp = {'A','B','C','D'}
3. main() 메서드
- 정의
- 자바 응용프로그램의 실행 시작 메서드
- main(String[] args) 메서드의 인자 전달
- main() 메소드의 매개변수로 명령행 인자의 전달
- String형태로 인자 받음
package day03;
public class Calc {
public static void main(String[] args) {
double sum = 0.0;
for(int i=0; i<args.length; i++) // 인자 개수만큼 반복
sum += Double.parseDouble(args[i]); // 문자열을 실수(double 타입)으로 변환하여 합산
System.out.println("합계: " + sum);
}
}
// args: [2, 20.5, 88.1]
// [출력] => 합계: 110.6
4. 예외 처리
4.1 프로그램 오류(에러)
- 오류 종류 (발생 시점에 따른)
- 컴파일 에러(compile-time error) : 컴파일 시에 발생하는 에러
- 런타임 에러(runtime error) : 실행 도중에 발생하는 에러
- 논리적 에러(logical error) : 컴파일도 잘되고 실행도 잘되지만 의도와 다르게 동작 - 런타임 에러에서의 오류
- 에러(error) : 프로그램 코드에 의해 수습 불가능한 심각한 오류
- 예외(exception) : 프로그램 코드에 의해 수승 가능한 미약한 오류 - 오류(컴파일 에러, 런타임 에러) 처리 과정
- 소스 코드를 컴파일하면 컴파일러가 소스코드에 대해 잘못된 부분에 대한 검사를 수행하여 오류 찾으면 에러 발생
→ 수정 후 컴파일 성공 → 클래스 파일 생성 → 런타임 에러 발생(실행 중 동작 중지 및 종료 등)
→ 런타임 에러의 잠재적인 오류 방지하기 위해, 수습 가능한 예외를 처리하여 비정상적인 프로그램 종료 차단
- 예외 개념
- 오동작이나 결과에 악영향을 미칠 수 있는 실행 중 발생한 오류
ex) 정수를 0으로 나누는 경우, 배열보다 큰 인덱스로 원소 접근, 존재하지 않은 파일 읽을 경우
- 자바에서 예외 처리 가능
- 예외가 발생하면 플랫폼이 인지하여 응용프로그램에서 전달
- 예외 처리하지 않으면, 응용프로그램 강제 종료
나뉨수를 입력하시오:100
나눗수를 입력하시오:0
Exception in thread "main" java.lang.ArithmeticException: / by zero
at DivideByZero.main(ExceptionExample1.java:14)
4.2 예외 클래스의 계층구조
- 예외 클래스
- RuntimeException 클래스들
- 프로그래머의 실수로 발생하는 예외 → 예외처리 필수
- RuntimeException 클래스와 그 자손 클래스
- ex) 배열 범위 초과, 클래스 간의 형 변환 오류, 정수를 0으로 나누는 오류
- Exception 클래스들
- 사용자의 실수와 같은 외적인 요인에 의해 발생하는 예외 → 예외처리 선택
- RuntimeException 클래스들을 제외한 나머지 클래스
- ex) 존재하지 않은 파일 입력, 클래스 이름 입력 오류, 데이터 형식 오류
4.3 예외 처리 (1) : try-catch-finally문
- 정의
- 프로그램 실행 시 발생하는 예외를 대응하는 응용프로그램 코드
- 프로그램의 비정상적인 종료 막고, 정상적인 실행 상태 유지를 위한 것 - 예외 처리 구문
- try-catch-finally 문 사용 (finally블록은 생략 가능)
- catch 블록
- 일치하는 catch블록 없으면 예외 처리 X
- 예외의 최고 조상인 Exception을 처리하는 catch블록은 모든 종류의 예외 처리 가능
- 발생한 예외 객체를 catch블록의 참조변수로 접근 가능
class ExceptionEx08 {
public static void main(String args[]) {
System.out.println(1);
System.out.println(2);
try {
System.out.println(3);
System.out.println(0/0); // 예외발생!!!
System.out.println(4); // 실행되지 않는다.
} catch (ArithmeticException ae) {
ae.printStackTrace();
System.out.println("예외메시지 : " + ae.getMessage());
} // try-catch의 끝
System.out.println(6);
} // main메서드의 끝
}
// [ 출력 ]
1
2
3
java.lang.ArithmeticException: / by zero
at ch03_반복문_배열_예외처리.자바의정석.예외처리.ExceptionEx08.main(ExceptionEx08.java:8)
예외메시지 : / by zero
6
- 멀티 catch 블럭
- 여러 catch블록을 '|' 기호를 통해 하나의 catch 블록으로 합치기 (JDK 1.7 이후)
- 중복된 코드 감소
- '|' 기호를 통해 연결할 수 있는 예외 클래스의 개수 제한 X
- 연결된 예외 클래스가 조상과 자손 관계 → 오류 발생 ⇒ [해결] 조상 클래스만 쓰기!!
- 연결된 예외 클래스들의 공통분모인 조상 예외 클래스에 선언된 멤버 사용 가능 O
- 어떤 예외가 발생한 것인지 확인 → instanceof 사용
- 멀티 catch 블록에 선언된 참조 변수 e는 상수 → 변경 X
// 멀티 catch 블럭 적용 전
try {
...
} catch (ExceptionA e) {
e.printStackTrace();
} catch (ExceptionB e2) {
e2.printStackTrace();
}
// 멀티 catch 블럭 적용 후
try {
...
} catch (ExceptionA | ExceptionB e) {
e.printStackTrace();
}
// 컴파일 에러 발생 ERROR : 조상과 자손과 관계 있음
try {
...
} catch (ParentExceptionA | ChildException e) { // ERROR
e.printStackTrace();
}
// OK: 조상 클래스만 사용 -> 불필요한 코드 제거
try {
...
} catch (ParentExceptionA e) { // ERROR
e.printStackTrace();
}
// 어떤 예외 발생한 것인지 확인 -> instanceof
try {
...
} catch (ExceptionA | Exception e) {
e.methodA; // ERROR: ExceptionA에 선언된 methodA() 호출 X
if(e instanceof ExceptionA) {
ExceptionA e1 = (ExceptionA)e;
e1.methodA(); // OK: ExceptionA에 선언된 methodA() 호출 O
}
else { // if(e instanceof ExceptionB)
...
}
}
- finally 블럭
- 예외 발생 여부와 상관없이 실행되는 코드
- 선택적으로 사용 가능(= 생략 가능)
- try 또는 catch블록에서 return문을 만나도 finally블록은 수행 - 자주 발생하는 예외
- 예제
package day03;
import java.util.Scanner;
public class DivideByZeroHandling {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while(true) {
System.out.print("나뉨수를 입력하시오: ");
int dividend = sc.nextInt(); // 나뉨수 입력
System.out.print("나눗수를 입력하시오: ");
int divisor = sc.nextInt(); // 나눗수 입력
try {
System.out.println(dividend + "를 " + divisor + "로 나누면 몫은 " + dividend/divisor + "입니다.");
break; // 정상적인 나누기 완료 후 while 벗어나기
}
catch(Exception e) {
System.out.println("0으로 나눌 수 없습니다. 다시 입력하세요.");
}
}
sc.close();
}
}
4.4 예외 처리 (2) : throws(예외 던지기)
- 메서드에 예외 선언
- 예외를 처리하는 또 다른 방법
- 메서드 선언부에 키워드 throws를 사용해서 메서드 내에서 발생할 수 있는 예외를 적고,
이 메서드를 호출하고자 하는 메서드에서 해당 예외 처리
- 메서드들을 통해 예외가 계속 전달되다가 main 메서드에서도 처리되지 않으면, main 메서드가 종료
→ 프로그램 종료 ⇒ 비정상적 종료 발생
- 어느 한 곳에서는 반드시 try-catch문으로 예외처리해주어야 함
void method() throws Exception1, Exception2, ... , ExceptionN { // ','로 여러 예외 메서드에 선언
...
}
class ExceptionEx14 {
public static void main(String[] args) {
try {
method1();
} catch (Exception e) {
System.out.println("main메서드에서 예외가 처리되었습니다.");
e.printStackTrace();
}
} // main메서드의 끝
static void method1() throws Exception {
throw new Exception();
} // method1()의 끝
} // class의 끝
// [ 출력 ]
main메서드에서 예외가 처리되었습니다.
java.lang.Exception
at ch03_반복문_배열_예외처리.자바의정석.예외처리.ExceptionEx14.method1(ExceptionEx14.java:14)
at ch03_반복문_배열_예외처리.자바의정석.예외처리.ExceptionEx14.main(ExceptionEx14.java:6)
4.5 예외 발생시키기 : throw
- 키워드 throw 사용하여, 그 위치에서 예외 발생시킴
- 예외 발생 과정
1. 연산자 new를 이용하여 발생시키려는 예외 클래스의 객체를 만듦
2. 키워드 throw를 이용해서 예외 발생
// 1
Exception e = new Exception("고의로 발생시켰음");
// 2
throw e;
// 1 + 2 : 한번에 예외 발생
throw new Exception("고의로 발생시켰음");
- 예제
class ExceptionEx09 {
public static void main(String args[]) {
try {
Exception e = new Exception("고의로 발생시켰음.");
throw e; // 예외를 발생시킴
// throw new Exception("고의로 발생시켰음.");
} catch (Exception e) {
System.out.println("에러 메시지 : " + e.getMessage());
e.printStackTrace();
}
System.out.println("프로그램이 정상 종료되었음.");
}
}
// [ 출력 ]
에러 메시지 : 고의로 발생시켰음.
java.lang.Exception: 고의로 발생시켰음.
프로그램이 정상 종료되었음.
at ch03_반복문_배열_예외처리.자바의정석.예외처리.ExceptionEx09.main(ExceptionEx09.java:5)
4.6 자동 자원 반환 : try-with-resources문
- 개념
- try-catch문의 변형 (JDK 1.7 이후)
- 입출력에 사용되는 클래스 중에서 사용한 후 닫아 줘야 하는 자원을 자동으로 반환
- try블록의 괄호() 안에 선언한 변수는 try 블럭 내에서만 사용 가능 O
- 과정
- try-with-resources문의 괄호()안에 객체를 생성하는 문장을 넣으면, 이 객체는 따로 close()를 호출하지 않아도
try블록을 벗어나는 순간 자동적으로 close() 호출 → 그다음 catch블록 또는 finally 블록이 수행
// try-with-resource문 적용 X → 코드 복잡
try {
fis = new FileInputStream("score.dat");
dis = new DataInputStream(fis);
} catch(IOException ie) {
ie.printStackTrace();
} finally {
try {
if(dis != null)
dis.close();
} catch(IOException ie) {
ie.printStackTrace();
}
}
// try-with-resource문 적용 O
try (FileInputStream fis = new FileInputStream("score.dat");
DataInputStream dis = new DataInputStream(fis)) {
} catch(IOException ie) {
ie.printStackTrace();
} finally {
}
4.7 사용자 정의 예외 만들기
- 기존의 예외 클래스를 상속받아 새로운 예외 클래스 정의
- 메시지와 에러코드 값 저장하는 예외 클래스
class MyException extends Exception {
// 에러 코드 값을 저장하기 위한 필드 추가
private final int ERR_CODE;
MyException(String msg, int errCode){ // 생성자
super(msg); // 조상인 Exception클래스의 생성자 호출
ERR_CODE = errCode;
}
MyException(String msg){ // 문자열을 매개변수로 받는 생성자
this(msg, 100); // ERROR_CODE를 100(기본값)으로 초기화
}
public int getErrCode(){ // 에러 코드를 얻을 수 있는 메서드 추가
return ERR_CODE; // 이 메서드는 주로 getMassage()와 함께 사용
}
}
4.8 예외 되던지기(re-throwing)
- 예외를 처리한 후에 다시 예외를 생성해서 호출한 메서드로 전달
- 예외가 발생한 메서드와 호출한 메서드, 양쪽에서 예외 처리해야 하는 경우 사용
class ExceptionEx17 {
public static void main(String[] args)
{
try {
method1();
} catch (Exception e) {
System.out.println("main메서드에서 예외가 처리되었습니다.");
}
} // main메서드의 끝
static void method1() throws Exception {
try {
throw new Exception();
} catch (Exception e) {
System.out.println("method1메서드에서 예외가 처리되었습니다.");
throw e; // 다시 예외를 발생시킨다.
}
} // method1메서드의 끝
}
// [ 출력 ]
method1메서드에서 예외가 처리되었습니다.
main메서드에서 예외가 처리되었습니다.
4.9 연결된 예외(chained exception)
- 한 예외가 다른 예외를 발생
- 원인 예외(cause exception) : 다른 예외를 발생시키는 예외
try {
startInstall(); // 프로그램 설치에 필요한 준비를 한다.
copyFiles(); // 파일들을 복사한다.
} catch (SpaceException e) {
InstallException ie = new InstallException("설치중 예외발생");
ie.initCause(e);
throw ie;
} catch (MemoryException me) {
...
} finally {
...
} // try의 끝
[ 참조 ]
1. Java의 정석 3판 (지은이 : 남궁성)
2. 명품 JAVA Programming 개정 3판 (지은이 : 황기태, 김효수)
'JAVA' 카테고리의 다른 글
CH06. java.lang 패키지와 유용한 클래스 (0) | 2021.05.10 |
---|---|
[Tip] static 메서드의 오버라이딩 불가 (0) | 2021.05.07 |
CH05. 상속, 오버라이딩, package, 제어자, 다형성, 추상클래스, 인터페이스 (0) | 2021.05.03 |
CH04. 객체지향, 클래스와 객체, 변수와 메서드, 오버로딩, 생성자, this레퍼런스, 변수 초기화 (0) | 2021.04.29 |
CH02. 변수, 연산자, 조건문 (0) | 2021.04.27 |
댓글