사이먼's 코딩노트
[Java] 예외처리 / 접근제한자 본문
[예외처리]
- 예외 처리(Exception Handling) 이란, 프로그램 실행 시 발생할 수 있는 예기치 못한 예외의 발생에 대비하여 코드를 작성하는 것이다.
- Java 코드를 예외처리한다고 해서 프로그램의 예외 상황 자체를 막을 순 없다.
- 예외 처리의 목적은 예외 발생으로 인해 실행 중인 프로그램의 갑작스런 비정상적인 동작을 막고, 에러를 잡아 복구를 시도하거나 아니면 해당 예외 상황을 피하여 프로그램이 정상적으로 실행 상태를 유지할 수 있도록 하는 것이다.
- 우리는 이런 예외 상황를 try와 catch라는 구문을 이용해서 처리할 수 있다.
[case #1]
- 먼저, try - catch를 사용하여 나눗셈에서 발생할 수 있는 예외 상황을 처리하는 코드이다.
public class Main {
public static void main(String[] args) {
int rs = 계산기.나누다(10, 0);
System.out.println(rs);
}
}
class 계산기 {
static int 나누다(int a, int b) {
int rs;
try {
rs = a / b;
}
catch (ArithmeticException e) {
System.err.println("0으로 나눌 수 없습니다.");
rs = 0;
}
return rs;
}
}
- 계산기 클래스가 가지고 있는 나누다() 메서드는 매개변수로 정수를 2개 받고 있다.
- 나누다() 에는 넘겨받은 두 값을 서로 나눗셈을 하는데, 상식적으로 어느 숫자든 0으로 나누게 되면 무한대의 값을 나타낸다.
- Java에서는 0으로 나눗셈을 하는 상황을 ArithmeticException 이라는 에러를 통해 경고를 한다.
- 이런 예외 상황을 막기 위해서 try - catch 문을 사용하였다.
- try - catch 문의 실행 절차는 try 안에 있는 코드를 수행하면서 예외사항이 발생하면 catch 안에 있는 코드를 실행한다.
- 만약 try 문을 수행했을 때 예외사항이 발생했다면 그 아래에 작성한 코드들은 무조건적으로 패스하고 바로 catch 문으로 넘어간다.
- catch() 문에서 () 안에는 예외 타입과 참조변수 e를 작성한다.
- 여기서는 try에서 특정 숫자를 0으로 나눠서 예외 상황이 발생했으니 catch로 넘어가서 에러 출력문을 출력하고 결과 값을 0으로 저장한다.
- 위 코드를 실행하면 아래 그림과 같이 에러 출력문과 함께 0이 return 된다.
- 위 코드처럼 클래스에 예외처리를 할 수도 있지만 Main에서도 예외처리가 가능하다.
- 다음은 Main 메서드에서 같은 예외처리를 한 코드이다.
public class Main {
public static void main(String[] args) {
int rs;
try {
rs = 계산기.나누다(10, 0);
}
catch (ArithmeticException e) {
System.err.println("0으로 나눌 수 없습니다.");
rs = 0;
}
System.out.println(rs);
}
}
class 계산기 {
static int 나누다(int a, int b) throws ArithmeticException {
int rs = a / b;
return rs;
}
}
- 첫번째 코드와 다른점은 try - catch 문이 Main 메서드로 위치하고 계산기 클래스에 throws ArithmeticException이 나누다() 메서드 뒤에 추가 작성되었다.
- throws는 자신을 호출하는 메서드에 예외처리의 책임을 떠넘기는 것이다.
- 쉽게 말해 나누다() 메서드를 호출한 Main 메서드에서 예외처리를 넘겨주라는 뜻이다.
- 더 쉽게 말해 나누다() 메서드를 호출할 때 다음과 같은 예외 상황이 있으니 조심해라는 전달하는 경고문이라고 생각하면 좋다.
- 위 코드도 실행했을 때 첫번째 코드와 동일한 출력문을 출력하게 된다.
[case #2]
- 다음은 try - catch 사용하여 배열의 크기가 초과했을 때 발생하는 예외 상황을 처리하는 코드이다.
public class Main {
public static void main(String[] args) {
int[] datas = new int[2];
채우기_3개_그리고_나누기(datas, 10, 0);
for ( int i = 0; i < datas.length; i++ ) {
System.out.println("datas[" + i + "] : " + datas[i]);
}
}
static void 채우기_3개_그리고_나누기(int[] datas, int a, int b) {
for(int i = 0; i < 3; i++) {
try {
datas[i] = a;
}
catch (ArrayIndexOutOfBoundsException e) {
System.err.println("배열의 크기를 3 이상으로 늘려주세요");
break;
}
}
for(int i = 0; i < datas.length; i++) {
try {
datas[i] = datas[i] / b;
}
catch (ArithmeticException e) {
System.err.println("0으로 나눌 수 없습니다.");
datas[i] = 0;
}
}
}
}
- Main 메서드를 살펴보면 datas은 정수 타입의 총 2개의 공간이 있는 배열이다.
- 채우기_3개_그리고_나누기() 메서드는 매개변수로 배열, 정수 2개를 받고, 역할은 배열 3개의 공간에 숫자를 채워넣고, 채워진 숫자를 특정 숫자로 나눗셈을 실행하여 해당 결과물을 다시 배열에 저장한다.
- 여기서 발생하는 예외 상황은 2가지이다.
- 먼저, 위에서 다뤘던 0으로 나눗셈을 하는 상황과 두번째로 배열의 크기가 이미 2로 선언이 되었는데 3개의 숫자를 채우려고 하는 상황이다.
- 이처럼 초기에 정해진 배열의 크기보다 더 많은 양의 데이터를 넣고자 할 때 ArrayIndexOutOfBoundsException 예외가 발생한다.
- 해당 에러는 앞으로 코드를 작성하면서도 수없이 많이 볼 수 있는 에러이기 때문에 잘 익혀두는 것이 좋다.
- 채우기_3개_그리고_나누기() 메서드에서는 반복문을 통해 배열에 값을 넣을 때 try - catch문을 사용해서 datas 배열의 3번째 공간이 없다면 catch로 넘어가 에러 출력문을 출력하고 반복문을 종료한다.
- 위 코드를 실행하면 아래 그림과 같이 에러 출력문과 함께 0이 출력된다.
- 여기서 에러 출력문이 2번 출력되는 이유는 배열에 있는 모든 숫자를 0으로 나누려해서 2번 예외처리한 것이다.
- 이번에도 메서드에서 예외처리를 하지않고 Main에서 바로 예외처리를 해봅시다.
public class Main {
public static void main(String[] args) {
int[] datas = new int[2];
try {
채우기_3개_그리고_나누기(datas, 10, 0);
}
catch (ArrayIndexOutOfBoundsException e) {
System.err.println("배열의 크기를 3 이상으로 늘려주세요.");
}
catch (ArithmeticException e) {
System.err.println("0으로 나눌 수 없습니다.");
}
catch (Exception e) {
System.err.println("알 수 없는 이유로 수행되지 않았습니다.");
}
for ( int i = 0; i < datas.length; i++ ) {
System.out.println("datas[" + i + "] : " + datas[i]);
}
}
static void 채우기_3개_그리고_나누기(int[] datas, int a, int b) throws ArrayIndexOutOfBoundsException, ArithmeticException, Exception {
for(int i = 0; i < 3; i++) {
datas[i] = a;
}
for(int i = 0; i < datas.length; i++) {
datas[i] = datas[i] / b;
}
}
}
- 첫번째 코드와 다른점은 try - catch 문이 Main 메서드로 위치하고 채우기_3개_그리고_나누기() 메서드 뒤에 throws를 작성해여 해당되는 예외 상황들을 추가하였다.
- Main 메서드를 보면 알 수 있듯이, catch은 꼭 한 번만 쓰는 것이 아니라 잡아낼 수 있는 예외라면 계속 작성이 가능하다.
- 예외 처리중 Exception 에러는 모든 예외의 최상위 단계라고 생각하면 되고 위 코드에서는 혹시모를 다른 예외를 잡기 위해 하나의 케이스로 추가했다.
- 위 코드를 실행시켜 보면 일단 우선적으로 ArrayIndexOutOfBoundsException 에러가 발생하기 때문에 "배열의 크기를 3 이상으로 늘려주세요" 라는 출력문만 출력되게 된다.
- 만약 배열의 크기에 대한 문제를 해결했다면 그 다음 예외인 ArithmeticException이 발생하여 "0으로 나눌 수 없습니다"가 출력될 것이다.
[접근제한자]
- 접근 제한자는 말 그대로 접근을 제한하기 위해 사용된다.
- 여기서 접근이란 클래스 및 인터페이스 그리고 이들이 가진 멤버 변수(인스턴스 변수)의 접근을 의미한다.
- 어떤 경우에는 클래스와 인터페이스를 다른 패키지에서 사용하지 못하도록 막을 필요가 있을 때도 있다.
- 그리고 객체 생성을 막기 위해서 생성자 호출을 하지 못하게 하거나 필드나 메서드를 사용하지 못하도록 막아야 하는 경우도 있다.
- 이 때, 접근 제한자를 사용할 수 있다.
- 접근 제한자는 public, private, protected와 같이 세 가지 종류가 있다.
- public - 외부 클래스가 자유롭게 사용할 수 있도록 한다.
- private - 개인적이기 때문에 외부에서 사용할 수 없도록 한다.
- protected - 같은 패키지 또는 자식 클래스에서만 사용할 수 있도록 한다.
반응형
'Java > Java' 카테고리의 다른 글
[Java] Stream (0) | 2024.05.02 |
---|---|
[Java] 인터페이스 (2) | 2024.03.19 |
[Java] 제네릭 / HashMap / 정리 (0) | 2024.03.18 |
[Java] ArrayList (2) | 2024.03.18 |
[Java] 배열 / toString / equals / StringBuilder (2) | 2024.03.14 |