[7-4] 예외 처리
<예외는 언제 발생하는가>
FileNotFoundException : 존재 하지 않는 파일 열 때
ArithmeticException : 산술 문제
ArrayIndexOutOfBoundsException : 배열에 아무것도 없는 곳을 가리킬 때
<예외 처리하기>
try {
<수행할 문장 1>;
<수행할 문장 2>;
...
} catch(예외1) {
<수행할 문장 A>;
...
} catch(예외2) {
<수행할 문장 a>;
...
}
예외 X : catch 문장 수행 X
예외 O : catch 문장 수행 O
<finally>
예외 발생 → 프로그램 중지 or 예외 처리 : catch 구문 실행
but 예외 발생 → 반드시 실행 how ?
public class Sample {
public void shouldBeRun() {
System.out.println("ok thanks.");
}
public static void main(String[] args) {
Sample sample = new Sample();
int c;
try {
c = 4 / 0;
sample.shouldBeRun(); // 이 코드는 실행되지 않는다.
} catch (ArithmeticException e) {
c = -1;
}
}
}
sample.shouldBeRun() 메서드 반드시 실행 → finally 문 사용
public class Sample {
public void shouldBeRun() {
System.out.println("ok thanks");
}
public static void main(String[] args) {
Sample sample = new Sample();
int c;
try {
c = 4 / 0;
} catch (ArithmeticException e) {
c = -1;
} finally {
sample.shouldBeRun(); // 예외에 상관없이 무조건 수행된다.
}
}
}
예외 발생 여부에 상관없이 무조건 실행 !
<예외 활용하기 >
public class Sample {
public void sayNick(String nick) {
if("바보".equals(nick)) {
return;
}
System.out.println("당신의 별명은 "+nick+" 입니다.");
}
public static void main(String[] args) {
Sample sample = new Sample();
sample.sayNick("바보");
sample.sayNick("야호");
}
}
sayNick 메서드 : return으로 메서드 종료 → 별명 출력 X
<RuntimeException>
class FoolException extends RuntimeException {
}
public class Sample {
public void sayNick(String nick) {
if("바보".equals(nick)) {
throw new FoolException();
}
System.out.println("당신의 별명은 "+nick+" 입니다.");
}
public static void main(String[] args) {
Sample sample = new Sample();
sample.sayNick("바보");
sample.sayNick("야호");
}
}
return했던 부분 → throw new FoolException()
Exception in thread "main" FoolException
at Sample.sayNick(Sample.java:7)
at Sample.main(Sample.java:14)
RuntimeException : 실행 시 발생하는 예외
Exception : 컴파일 시 발생하는 예외 (예측 가능한 경우)
<Exception>
RuntimeException 상속 → Exception 상속 : 컴파일 오류
FoolException → Checked Exception : 예외 처리 강제
class FoolException extends Exception {
}
public class Sample {
public void sayNick(String nick) {
try {
if("바보".equals(nick)) {
throw new FoolException();
}
System.out.println("당신의 별명은 "+nick+" 입니다.");
}catch(FoolException e) {
System.err.println("FoolException이 발생했습니다.");
}
}
public static void main(String[] args) {
Sample sample = new Sample();
sample.sayNick("바보");
sample.sayNick("야호");
}
}
sayNick 메서드에서 try ~ catch 문으로 FoolException을 처리
<예외 던지기>
예외 위로 던지기 ♥
public class Sample {
public void sayNick(String nick) throws FoolException {
try { // try .. catch 문을 삭제할수 있다.
if("바보".equals(nick)) {
throw new FoolException();
}
System.out.println("당신의 별명은 "+nick+" 입니다.");
}catch(FoolException e) {
System.err.println("FoolException이 발생했습니다.");
}
}
public static void main(String[] args) {
Sample sample = new Sample();
sample.sayNick("바보");
sample.sayNick("야호");
}
}
sayNick 메서드 뒷부분에 throws 구문 이용 !
throw와 throws의 차이
throw: 메서드 내에서 예외를 발생시키는 데 사용
thorws: 메서드 선언부에서 사용, 해당 메서드가 처리하지 않은 예외를 호출자에게 전달
by throws 구문 , FoolException의 예외를 처리해야 하는 대상 : sayNick 메서드 → main 메서드
class FoolException extends Exception {
}
public class Sample {
public void sayNick(String nick) throws FoolException {
if("바보".equals(nick)) {
throw new FoolException();
}
System.out.println("당신의 별명은 "+nick+" 입니다.");
}
public static void main(String[] args) {
Sample sample = new Sample();
try {
sample.sayNick("바보");
sample.sayNick("야호");
} catch (FoolException e) {
System.err.println("FoolException이 발생했습니다.");
}
}
}
☞ sayNick 메서드에서 처리 vs main 메서드에서 처리 ☜
얜 다 실행 됨 얜 두번째 문장이 실행 X
왜냐면 첫번째 문장 예외 발생 : catch 문으로 빠져버리기 때문
<트랜잭션>
트랜잭션 : 하나의 작업 단위
모두 취소하는 행위 : 롤백
데이터 정합성 : 데이터들의 값이 서로 일관성 있게 일치하는 것
상품발송() {
포장();
영수증발행();
발송();
}
포장() {
...
}
영수증발행() {
...
}
발송() {
...
}
쇼핑몰 운영자는 ‘포장’, ‘영수증발행’, ‘발송’이라는 3가지 작업 중 1가지라도 실패하면 모든 작업을 취소하고 싶어함
트랜잭션 처리 방법 : 포장, 영수증발행, 발송 메서드에서는 각각 예외를 던지고 상품발송 메서드에서 던져진 예외를 처리한 뒤 모두 취소 !
상품발송() {
try {
포장();
영수증발행();
발송();
}catch(예외) {
모두취소(); // 하나라도 실패하면 모두 취소한다.
}
}
포장() throws 예외 {
...
}
영수증발행() throws 예외 {
...
}
발송() throws 예외 {
...
}
[7-5 스레드]
프로세스 : 한개 일
ㅅㅡ레드 : 두 가지 또는 그 이상의 일을 동시에
코테 2 번 문제
<문제>
어떤 단어를 뒤에서부터 읽어도 똑같다면 그 단어를 팰린드롬이라고 한다. 'radar', 'sees'는 팰린드롬이다.
수도 팰린드롬으로 취급할 수 있다. 수의 숫자들을 뒤에서부터 읽어도 같다면 그 수는 팰린드롬수다. 121, 12421 등은 팰린드롬수다. 123, 1231은 뒤에서부터 읽으면 다르므로 팰린드롬수가 아니다. 또한 10도 팰린드롬수가 아닌데, 앞에 무의미한 0이 올 수 있다면 010이 되어 팰린드롬수로 취급할 수도 있지만, 특별히 이번 문제에서는 무의미한 0이 앞에 올 수 없다고 하자.
<입력>
입력은 여러 개의 테스트 케이스로 이루어져 있으며, 각 줄마다 1 이상 99999 이하의 정수가 주어진다. 입력의 마지막 줄에는 0이 주어지며, 이 줄은 문제에 포함되지 않는다.
<출력>
각 줄마다 주어진 수가 팰린드롬수면 'yes', 아니면 'no'를 출력한다.
<풀이>
import java.util.Scanner;
public class Main {
// 팰린드롬 수 판별 함수
public static boolean isPalindrome(String number) {
int len = number.length();
for (int i = 0; i < len / 2; i++) {
if (number.charAt(i) != number.charAt(len - i - 1)) {
return false;
}
}
return true;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (true) {
String num = sc.nextLine().trim();
// 입력이 '0'이면 종료
if (num.equals("0")) {
break;
}
// 팰린드롬 수 판별 및 출력
if (isPalindrome(num)) {
System.out.println("yes");
} else {
System.out.println("no");
}
}
sc.close();
}
}
- public static boolean isPalindrome(String number) {:
팰린드롬인지 확인하는 메서드- public: 다른 클래스에서도 이 메서드를 호출할 수 있게 설정
- static: 객체를 생성하지 않고도 메서드를 호출할 수 있게 설정
- boolean: 이 메서드는 true 또는 false를 반환
- String number: 숫자를 문자열 형태로 받아 팰린드롬 여부를 확인
- int len = number.length();:
입력된 문자열 number의 길이 구하기. 길이는 비교 반복문의 범위를 결정하는 데 사용
- for (int i = 0; i < len / 2; i++) {:
문자열의 앞쪽 절반과 뒤쪽 절반을 비교하기 위해 반복문 사용- i는 문자열의 앞부분 인덱스 나타냄
- 반복은 문자열의 길이의 절반(len / 2)까지만 수행.
- if (number.charAt(i) != number.charAt(len - i - 1)) {:
문자열의 앞쪽 문자(number.charAt(i))와 뒤쪽 문자(number.charAt(len - i - 1))를 비교- charAt(i): i번째 문자 반환
- charAt(len - i - 1): 문자열 뒤쪽에서 i번째 문자 반환
- 두 문자가 다르면 팰린드롬이 아니므로 false 반환
- return false;:
문자열이 팰린드롬이 아니면 즉시 false를 반환하여 메서드 종료
- return true;:
반복문이 끝날 때까지 서로 다른 문자가 없으면 팰린드롬이므로 true 반환
- public static void main(String[] args) {:
실행 시작
- Scanner sc = new Scanner(System.in);:
Scanner 객체를 생성하여 사용자로부터 입력받기- System.in: 표준 입력 스트림(키보드 입력)
- String num = sc.nextLine().trim();:
사용자로부터 한 줄의 입력을 받아 공백을 제거한 문자열로 반환
- if (num.equals("0")) {:
입력된 문자열이 "0"인지 확인합니다.- "0"이면 입력이 종료 조건을 만족하므로 프로그램 종료
- if (isPalindrome(num)) {:
입력된 문자열 num이 팰린드롬인지 확인- isPalindrome(num)이 true를 반환하면 "yes" 출력
- System.out.println("yes");:
문자열 num이 팰린드롬이면 "yes"를 출력
- else {:
isPalindrome(num)이 false를 반환한 경우 실행
- System.out.println("no");:
문자열 num이 팰린드롬이 아니면 "no"를 출력
- sc.close();:
Scanner 객체를 닫아 입력 스트림 해제