컴파일 에러: 컴파일 시 발생
런타임 에러: 실행도중 발생
->에러(error): 프로그램 코드에 의해서 수습할 수 없는 심각한 오류
->예외(exception): 프로그램 코드에 의해서 수습 가능한 미약한 오류
Exception클래스와 그 자손들: 사용자의 실수와 같이 외적인 요소에 의해 발생(checked예외-예외처리 필수!)
RuntimeException클래스와 그 자손들: 프로그래머의 실수로 발생(unchecked예외 예외처리 선택!)
논리적 에러: 실행은 되지만, 의도와 다르게 동작
try{
try{ } catch(Exception e){ } //try 또는 catch 블럭에 try-catch포함 가능
}catch(Exception **e**){ //변수 e 중복선언. 에러 참조변수 영역이 겹치기 때문에
try{ } catch(Exception **e**){ }
//catch 블럭 괄호에 선언된 변수는 캐치블럭 내에서만 사용가능
} catch(Exception e2){
//예외처리
}
printStackTrace() 예외발생 당시 호출스택(Call Stack)에 있었던 메서드의 정보와 예외 메시지를 화면에 출력
getMessage() 발생한 예외클래스의 인스턴스에 저장된 메시지를 얻는다.
class Exception {
public void static main(String args[]){
System.out.println(1);
System.out.println(2);
try{
System.out.println(3);
System.out.println(0/0); //예외발생 catch문으로 넘어감
System.out.println(4); //실행x
} catch(ArithmeticException ae){
ae.printStackTrace();
System.out.println("예외메시지 : " + ae.getmessage());
}
System.out.println(9);
}
}
실행결과
1
2
3
java.lang.ArithmeticExeption: /by zero //예외발생 원인
at Exception.main(Exception.java:7) //예외발생 위치
예외메시지: /by zero
9
멀티 catch블럭-코드 중복을 제거하기 위해 ' | '기호를 사용하여 catch 블럭을 하나로 합칠 수 있다. (자주 쓰이지는 않는다.)
try {
//내용입력
}catch(ParentException|ChildException e){ //예외클래스가 조상, 자손 관계에 있으면 컴파일에러 조상클래스 하나만 써줘도 되기때문
e.printStackTrace();
}
try {
//내용입력
} catch(ExceptionA|ExceptionB e) {
e.methodA(); //에러. catch블럭을 합쳤을때는 어떤 예외클래스의 인스턴스가 객체로 연결되었는지 알 수 없음 So ExceptionA ,B의 공통 멤버만 사용 가능
//여기서 선언된 참조변수e는 여러 catch블럭이 공유하는 상수이므로 값을 변경하는 것은 불가
키워드 throw를 사용해 예외를 발생시킬 수 있다.
메서드 선언부에 thrwos키워드를 사용하여 예외를 선언해줄 수 있다.
import java.io.*;
class Exception{
public static void main(String args[]){
try{
File f = createFile(args[0]); //args[0]-커멘드 라인을 통해서 입력받음 직접 입력도 가능=createFile(test.txt)
System.out.println(f.getName()+"파일이 성공적으로 생성되었습니다.");
} catch (Exception e) { //createFile메서드로부터 예외를 받아서 처리
System.out.println(e.getMessage()+"다시 입력해주시기 바랍니다.");
}
}
static File createFile(String fileName) throws Exception{//예외 선언후 try-cath문이 있는 main메서드로 예외 던짐
if(fileName==null || fileName.equals(""))
throw new Exception("파일이름이 유효하지 않습니다."); //객체를 만들고 예외 발생시킴
File f = new File(fileName);
f.creatNewfile();
return f;
}
}
실행결과
c:\jdk1.9\work\ch8>java Exception test.txt
test.txt 파일이 성공적으로 생성되었습니다.
c:\jdk1.9\work\ch8>java Exception ""
파일이름이 유효하지 않습니다. 다시 입력해주시기 바랍니다.
try-catch문은 예외가 발생한 메서드 자체에서 직접 처리하든지 호출한 메서드에서 처리하든지 둘중 하나엔 존재해야함
사용자 정의 예외 만들기
1.Exception클래스 혹은 RuntimeException클래스 중 어떤걸 조상으로 선택할건지 결정 (Exception은 예외처리가 필수이기 때문에 가능하면 RuntimeException 사용하기)class MyException extends Exception{ MyException(String msg){//대부분 String 매개변수가 있는 생성자를 만들어준다. super(msg); //조상클래스 생성자의 msg호출
class Exception{
public static void main(String args[]){
try{
method1();
} catch(Exception e) {
System.out.println("main메서드에서 예외가 처리되었습니다.");
}//받은 예외를 처리함
}
static void method1() throws Exception{
try{
throw new Exception();
} catch(Exception e) {
System.out.println("method1메서드에서 예외가 처리되었습니다."); //예외처리함
throw e; //예외를 다시 발생시킴
}
}
}
특별히 어디에 쓰인다는 케이스는 없지만 예외를 분담해서 처리해야 할 때 이렇게 처리할 수도 있다.
한 예외를 다른 예외에 포함시켜 연결해줌
Why?
1.예외가 많아지면 그만큼 catch블록이 많아지기 때문에 묶어서 다루면 코드의 길이를 줄일 수 있다.
void install throws InstallException //세부적인 예외처리는 InstallException으로 감싸서 코드의 길이를 효율적으로 줄임
try{
startInstall();
copyFiles();
} catch(SpaceException e){//예외A
InstallException ie = new InstallException("설치중 예외발생"); //예외B 생성
ie.initCause(e);//InstallException(예외B)의 원인 예외를 SpaceException(예외A)으로 지정
throw ie; //예외A를 처리했지만 예외B를 던짐
Throwable initcause(Throwable cause) 지정한 예외를 원인 예외로 등록하는 생성자
Throwable getcause() 원인 예외를 반환
satic void startInstall() throws SpaceExcepion, MemoryExcepion{
if(!enoughSpace())
throw new SpaceException("설치할 공간이 부족합니다.");
if(!enoughMemory())
throw new MemoryException("메모리가 부족합니다.");
}
↓↓↓↓
satic void startInstall() throws SpaceExcepion{//Memory를 선택처리로 바꾸었기 때문에 안써줘도 됌
if(!enoughSpace())
throw new SpaceException("설치할 공간이 부족합니다.");
if(!enoughMemory())
throw new RuntimeException(new MemoryException("메모리가 부족합니다."));
}// RuntimeException(Thrwoable cause)원인 예외를 등록하는 생성자
출처: 자바의 정석3rd Edition 8장 예외처리