ex) 문제상황 = 나가야 하는데 문이 안 열림
-> 어떻게든 나가는 법을 알려준다. (x)
-> 차분히 앉아 강사님을 기다린다. (o) - 즉, 대안 제시
class ExceptionEx1 {
public static void divide(int num1, int num2) {
int result = num1 / num2;
System.out.println(result);
}
public static void main(String[] args) {
divide(12, 6);
divide(12, 0);
System.out.println("end of main");
}
}
try {
// 기본적으로 수행하려는 문장
} catch(예외클래스 e) {
// 예외 발생시 수행할 문장
}
try {
// 기본적으로 수행하려는 문장
} [catch(예외클래스 e) {
// 예외 발생시 수행할 문장
}] finally {
// 예외가 발생하든 하지 않든 반드시 수행할 문장
}
- stack vs. queue
- 에러 표시에 나오는
클래스.메서드
구조는 static이라 나오는 게 아님.
속한 클래스를 알려주려는 것.
(저 부분은 코드가 아니므로 자바 코드의 규칙이 적용되지 않는다.)
java.lang.ArithmeticException
: 0으로 나눈 연산 객체 e.printStackTrace();
System.out.println(e.getMessage());
class ExceptionEx1 {
public static void divide(int num1, int num2) {
String s;
try {
s = "Try";
System.out.println("start of try"); // 1번, 5번
int result = num1 / num2;
// 예외가 발생할 수 있는 연산
System.out.println(result); // 2번
// 위 연산에 의존성을 가진 연산. try에 넣어 같이 처리!
System.out.println("end of try"); // 3번
} catch(ArithmeticException e) {
s = "Catch";
// ArithmeticException : 0으로 나눈 연산
// 대신 할 일을 정의
System.out.println("0으로 나눌 수 없습니다."); // 6번
System.out.println("end of catch"); // 7번
}
// try 안에서 예외가 발생하면 바로 catch로 넘어간다.
System.out.println(s); // 4번, 8번
}
public static void main(String[] args) {
divide(12, 6);
divide(12, 0);
System.out.println("end of main"); // 9번
}
}
class ExceptionEx3 {
public static void makeException(int[] arr) {
int length = arr.length;
System.out.println("배열의 길이 : " + length);
}
public static void main(String[] args) {
makeException(new int[] {1, 2, 3, 4, 5, 6, 7});
makeException(null);
System.out.println("end of main");
}
}
class ExceptionEx3 {
public static void makeException(int[] arr) {
try {
int length = arr.length;
System.out.println("배열의 길이 : " + length);
} catch(NullPointerException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
makeException(new int[] {1, 2, 3, 4, 5, 6, 7});
makeException(null);
System.out.println("end of main");
}
}
class ExceptionEx4 {
public static void makeException(String str) {
// String -> int
// "123" -> 123
int num = Integer.parseInt(str);
num++;
System.out.println(num);
}
public static void main(String[] args) {
makeException("123");
makeException("???");
}
}
class ExceptionEx4 {
public static void makeException(String str) {
// String -> int
// "123" -> 123
try {
int num = Integer.parseInt(str);
num++;
System.out.println(num);
} catch(NumberFormatException e) {
System.out.println("Message : " + e.getMessage());
}
}
public static void main(String[] args) {
makeException("123");
makeException("???");
}
}
- Integer.parseInt(str)
: String -> int- String.valueOf(data)
: (대충 모든 기초 자료형) -> String
- catch문 조건 묶기 (예외1 | 예외2 e)
예외 처리시에 수행할 코드가 같은 경우, 한 번에 처리 가능 (JDK 1.7~)class ExceptionEx5 { public static void makeException(Shoes s, String str) { try { int price = s.getPrice(); int num = Integer.parseInt(str); } catch(NullPointerException | NumberFormatException e) { System.out.println("예외가 발생했습니다."); } } public static void main(String[] args) { makeException(null, "123"); makeException(new Shoes(50000), ""); } }
- 하나의 try에 여러 개의 catch 연결 가능 (다양한 예외의 경우 대비)
- 처리되는 예외들 간에 계층구조가 존재하는 경우 반드시 하위 예외부터 처리해야 한다. (체크예외)
import java.io.*;
class CommonObj {
public void doSomething() {
try {
FileReader fr = new FileReader("a.txt");
} catch(FileNotFoundException e) {
System.out.println("catch");
}
}
}
class UserA {
public void useCommonObj(CommonObj obj) {
// 문제발생 : do A
obj.doSomething();
}
}
class UserB {
private CommonObj obj = new CommonObj();
// 문제발생 : do B
public void doit() {
obj.doSomething();
}
}
class ExceptionEx1 {
public static void main(String[] args) {
UserA a = new UserA();
UserB b = new UserB();
a.useCommonObj(new CommonObj());
b.doit();
}
}
import java.io.*;
class CommonObj {
public void doSomething() throws FileNotFoundException {
FileReader fr = new FileReader("a.txt");
}
}
class UserA {
public void useCommonObj(CommonObj obj) {
// 문제발생 : do A
try {
obj.doSomething();
} catch(FileNotFoundException e) {
System.out.println("do A");
}
}
}
class UserB {
private CommonObj obj = new CommonObj();
// 문제발생 : do B
public void doit() {
try {
obj.doSomething();
} catch(FileNotFoundException e) {
System.out.println("do B");
}
}
}
class ExceptionEx1 {
public static void main(String[] args) {
UserA a = new UserA();
UserB b = new UserB();
a.useCommonObj(new CommonObj());
b.doit();
}
}
파일을 관리하는 총책임자 os
내가 파일을 읽고 싶다면 os에게 권한을 받아와야 함
그 외의 외부 자원을 사용하는 방식도 비슷함
자바 가상머신도 결국 컴퓨터 자원을 사용하는 프로그램의 하나이기 때문
import java.io.*;
class CommonObj {
public void doSomething() throws FileNotFoundException {
FileReader fr = null;
try {
fr = new FileReader("a.txt");
} finally {
// finally 주 용례 : 자원해제
try {
fr.close(); // fr.close() <- 자원해제
} catch(Exception e) {
}
System.out.println("CommonObj 후처리");
// 사용자에게 완료 알림
}
}
}
class UserA {
// 문제발생 : do A
public void useCommonObj(CommonObj obj) {
try {
obj.doSomething();
} catch(FileNotFoundException e) {
System.out.println("do A");
}
}
}
class UserB {
private CommonObj obj = new CommonObj();
// 문제발생 : do B
public void doit() {
try {
obj.doSomething();
} catch(FileNotFoundException e) {
System.out.println("do B");
}
}
}
class ExceptionEx1 {
public static void main(String[] args) {
UserA a = new UserA();
UserB b = new UserB();
}
}
// throws를 사용하면 문제 상황이 발생했을 때 메서드를 호출한 사용자가 자신의 의도대로 처리할 수 있다.
// throws를 사용하지 않으면 메서드 호출한 사용자가 예외 발생 여부조차 알 수 없다.
지금까지 본 예외는 모두 기술적인 문제
이제는 우리가 원하는 예외 상황 클래스를 만들고 쓸 수 있어야 함
// 커스텀 예외 클래스 만들기
class MyException extends Exception {
public MyException() {
super("예외가 발생했어요");
}
public MyException(String msg) {
super(msg);
}
}
// 예외 발생시키는 방법
class ExceptionEx2 {
public static void makeException(int num) throws MyException {
try {
// num이 0보다 작은 경우 예외상황이라 정의함 : MyException
if(num < 0) {
MyException e = new MyException("이것은 예외!");
// 예외 발생
throw e;
} else {
System.out.println("num은 양수");
}
} finally {
System.out.println("이것은 finally");
}
}
public static void main(String[] args) {
try {
makeException(5);
} catch(MyException e) {
System.out.println(e.getMessage());
}
try {
makeException(-5);
} catch(MyException e) {
System.out.println(e.getMessage());
}
}
}
// 이걸 배우면 예외를 문제상황 말고 다른 의미로도 사용 가능
// 현재 예시에서는 if문과 비슷하게 사용(대체 가능)했지만 다양한 방향 사용 가능
class ExceptionEx3 {
public static void howToUse() {
int num = 0;
try {
while(true) {
System.out.println("looping");
num++;
if(num == 100) {
throw new Exception();
}
}
} catch(Exception e) {
System.out.println("Escaped!");
}
}
public static void main(String[] args) {
howToUse();
}
}
// roop문 깨는 조건으로도 사용 가능
// break 쓰는 것보다 예쁜 코드
// 예외를 프로그램을 끝낼 정도의 힘이 있다.
// 예외는 단순히 error의 의미가 아니다.
class Human {
private String name;
private int age;
public Human(String name, int age) {
setName(name);
setAge(age);
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void love(Human honey) throws CrazyHumanException{
if(honey.getAge() > 19) {
System.out.println(name + " loves " + honey.getName());
} else {
// 미성년자를 사랑... 이것은 예외
CrazyHumanException e = new CrazyHumanException();
throw e;
}
}
}
class CrazyHumanException extends Exception {
public CrazyHumanException() {
super("미친 인간입니다.");
}
public CrazyHumanException(String msg) {
super(msg);
}
}
class ExceptionEx4 {
public static void main(String[] args) {
Human h1 = new Human("해인", 34);
Human h2 = new Human("지민", 40);
try {
h1.love(h2);
} catch(CrazyHumanException e) {
System.out.println(e.getMessage());
}
Human h3 = new Human("수미", 17);
Human h4 = new Human("영수", 47);
try {
h4.love(h3);
} catch(CrazyHumanException e) {
System.out.println(e.getMessage());
}
Human h5 = new Human("착한 사람", 30);
try {
h5.love(h3);
} catch(CrazyHumanException e) {
System.out.println("그...럴수...도 있......나?");
}
}
}
// 특정한 코드 안에 if-else가 들어가면, 그 코드 내용은 정해져있음
// 그러나 예외처리를 이용하면 유연성이 생김. 다양성이 커짐.
// ex) 지금처럼 else 부분에 예외를 넣는 것으로 else가 수행할 일을 바꿀 수 있음