의미: exceptions는 예상치 못한 일이 발생했음을 나타내는 오류이다.
기능: dart code는 exceptions를 throw 하고 catch할 수 있다.
특징: dart는 exception과 error types를 제공하지만, null이 아닌 객체만 throw 할 수 있다.
exception발생 시 객체 또는 코드 등을 반환할 수 있다.
//일단 에러를 던져본다고 생각
throw 사용 코드 예)
//example 1
throw FormatException('Expected at least 1 section');
//example 2
throw 'Out of llamas!';
example 1 사용을 권장한다.
catch는 다양한 exception상황을 제시해서 특정 상황의 에러 상황을 제어한다.
-> 예외를 다시 발생시키지 않는 한 예외가 전파되지 않는다.
//exception을 catch 한다고 이해함
catch문을 여러 개 쓰면 다양한 종류의 에러 상황 제어 가능하다.
오류 상황 앞에 on을 쓰거나, catch를 사용한다.
<예시코드1>
try {
breedMoreLlamas();
} on OutOfLlamasException {
buyMoreLlamas();
}
//OutofLiamasException이라는 오류가 생기면 buyMoreLlamas()실행.
<예시코드2>
try {
breedMoreLlamas();
} on OutOfLlamasException {
// 지정해둔 특정 오류 상황(OutOfLlamas라는 오류 상황) 처리
buyMoreLlamas();
} on Exception catch (e) {
// exception 타입으로 지정한 오류 처리
// (위에 선언한 OutOfLlamasException는 제외)
print('Unknown exception: $e');
} catch (e) {
// 타입이 특정하게 지정되지 않은 나머지 오류 처리
print('Something really unknown: $e');
}
//한 경우씩 위에서부터 걸러서 내려온다고 생각
rethrow는 오류를 재전파한다. 함수의 오류를 볼 수 있게 하기 위해서 재전파 하는 것이다.
예외를 완전히 처리할 수 없는 경우 사용한다.
<예시코드>
void misbehave() {
try {
dynamic foo = true;
print(foo++); // 만약 여기서 런타임 오류가 났다면
} catch (e) { // 여기서 오류를 catch하고,
print('misbehave() partially handled ${e.runtimeType}.');
rethrow; // call한 함수(해당 예시에서는 main함수)가 이 오류 볼 수 있도록 재전파
}
}
void main() {
try {
misbehave(); // rethrow로 위에서 찾은 에러가 재전파되어 발생.
} catch (e) { // 에러를 catch
print('main() finished handling ${e.runtimeType}.');
}
}
finally는 예외 발생의 여부와 관계 없이 일부 코드가 실행되게 할 때 사용한다.
finally는 크게 두 가지 상황으로 나뉜다.
에러 상황에 알맞는 catch문이 있으면, catch문을 먼저 실행하고 finally 실행
실행 순서: catch문 -> finally
<예시코드>
try {
breedMoreLlamas();
} catch (e) {
print('Error: $e'); // 에러를 먼저 제어한다.
} finally {
cleanLlamaStalls(); // 그 다음, 함수를 실행한다.
}
에러 상황에 알맞는 catch문이 없으면 exception이 있어도 finally를 실행한다.
실행 순서: finally -> exception
<예시코드>
try {
breedMoreLlamas();
} finally {
// 에러가 발생하더라도 아래 호출된 함수 실행
cleanLlamaStalls();
//catch문이 없으므로 에러가 재전파 된다.
}
typedef VoidFunction = void Function();
class ExceptionWithMessage {
final String message;
const ExceptionWithMessage(this.message);
}
// Call logException to log an exception, and doneLogging when finished.
abstract class Logger {
void logException(Type t, [String? msg]);
void doneLogging();
}
void tryFunction(VoidFunction untrustworthy, Logger logger) {
// Invoking this method might cause an exception. Catch and handle
// them using try-on-catch-finally.
untrustworthy();
}
typedef VoidFunction = void Function();
class ExceptionWithMessage {
final String message;
const ExceptionWithMessage(this.message);
}
// Call logException to log an exception, and doneLogging when finished.
abstract class Logger {
void logException(Type t, [String? msg]);
void doneLogging();
}
void tryFunction(VoidFunction untrustworthy, Logger logger) {
// Invoking this method might cause an exception. Catch and handle
// them using try-on-catch-finally.
try {
untrustworthy();
} on ExceptionWithMessage catch (e) {
logger.logException(e.runtimeType, e.message);
} on Exception {
logger.logException(Exception);
} finally {
logger.doneLogging();
}
}
참고 사이트1: https://m.blog.naver.com/mingdyuo/221803704762
참고 사이트2: https://dart.dev/codelabs/dart-cheatsheet#initializer-lists