public interface Vehicle {
public void run();
}
public class Anonymous {
Vehicle field = new Vehicle () {
@Override
public void run() {
System.out.println("자전거가 달립니다.");
}
};
void method1() {
Vehicle localVar = new Vehicle() {
@Override
public void run() {
System.out.println("승용차가 달립니다.");
}
};
localVar.run();
}
void method2(Vehicle v) {
v.run();
}
}
public class AnonymousExample {
public static void main(String[] args) {
Anonymous anony = new Anonymous();
anony.field.run(); // 자전거
anony.method1(); // 승용차
anony.method2(new Vehicle() { // 트럭
@Override
public void run() {
System.out.println("트럭이 달립니다.");
}
});
}
}
public class ExceptionExample {
public static void main(String[] args) {
String str = "dudu-dudu-du";
int a = 10, b = 0;
try {
System.out.println(str.toString());
System.out.println(a/b);
} catch(NullPointerException e) {
System.out.println(e.getMessage());
} catch(ArithmeticException e) {
System.out.println(e.getMessage());
} catch(Exception e) {
System.out.println(e.getMessage());
}
System.out.println("프로그램 종료");
}
}
null
값을 갖는 변수에 객체 접근 연산자(.
)를 사용했을 때 발생하는 예외. 즉, 객체의 값이 없는데 사용하려 할 때 발생하는 예외이다.catch
문은 위에서 아래로 순서대로 처리되므로 순서에 유의해야 한다.Exception
은 모든 예외 상황에 대해 처리하는 것이기 때문에 가장 마지막에 처리하도록 해야 한다.public class ExceptionExample2 {
public static void main(String[] args) {
int[] arr1 = {10, 20, 30, 40};
int[] arr2 = {2, 0, 6};
for (int i = 0; i < arr1.length; i++) {
try {
System.out.println(arr1[i]/arr2[i]);
} catch (ArithmeticException e) {
System.out.println(e.getMessage());
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println(e.getMessage());
}
}
}
}
출력 결과
5
/ by zero
5
Index 3 out of bounds for length 3
public class ExceptionExample2 {
public static void main(String[] args) {
int[] arr1 = {10, 20, 30, 40};
int[] arr2 = {2, 0, 6};
try {
for (int i = 0; i < arr1.length; i++) {
System.out.println(arr1[i]/arr2[i]);
}
} catch (ArithmeticException e) {
System.out.println(e.getMessage());
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println(e.getMessage());
}
}
}
출력 결과
5
/ by zero
try
의 위치에 따라 예외 처리의 결과가 달라진다.public class ExceptionExample3 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int sel;
while(true) {
try {
System.out.println("숫자 입력>> ");
sel = Integer.parseInt(sc.nextLine());
break;
} catch (NumberFormatException e) {
System.out.println("숫자만 입력이 가능합니다.");
}
}
System.out.println("프로그램 종료");
}
}
int
로 선언되어 숫자 형태가 되어야 하지만 문자를 입력하면 숫자 형태로 변환이 불가능하여 NumberFormatException
이 발생NumberFormatException
처리를 할 때 try
-catch
를 while
문 안에 넣어서 숫자만 입력 가능하도록 처리할 수 있다.class A {}
class B extends A {}
class C extends A {}
public class ExceptionExample4 {
public static void main(String[] args) {
A a = new B();
try {
C c = (C)a;
} catch (ClassCastException e) {
System.out.println("Cast failed");
}
}
}
ClassCastException
발생instanceof
연산자를 활용해서 타입 변환이 가능한지 알아보는 것이 좋다.try
-catch
-finally
블록을 이용하여 예외 처리 코드 작성try
블록에는 예외가 발생 가능 코드 입력catch
블록에는 예외 발생 시 처리 코드를 입력하며 여러 개의 catch
블록이 올 수 있다.finally
블록은 생략 가능하며 예외 발생 여부에 상관없이 항상 반드시 실행해야 하는 코드 입력// try-catch-finally를 모두 사용한 예외 처리 코드 예시
public class ExceptionExample5 {
public static void main(String[] args) {
try {
String str = null;
System.out.println(str.toString());
System.out.println("try");
return;
} catch (Exception e) {
System.out.println("예외 처리");
return;
} finally { // 예외 발생할 때나 발생하지 않을 때나 반드시 처리. try나 catch문의 return 적용X
System.out.println("마무리 처리");
}
}
}
public class ExceptionExample6 {
public static void main(String[] args) {
try {
throw new Exception("내가 만든 예외");
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
throw
를 사용하여 예외를 직접 생성해서 떠넘길 수 있다.throw
를 해야 하지만 java
에 원래 있는 함수에는 throw
가 포함되어 있으므로 따로 throw
를 써주지 않아도 예외 처리가 된다.throw
를 사용한다.throws
로 작성해서 메소드에서 처리하지 않은 예외를 호출한 곳으로 떠넘긴다.throws
뒤에는 콤마(,
)로 구분하여 여러 개의 예외를 나열할 수 있다.public class ExceptionExample7 {
public static void method1() throws Exception {
method2();
}
public static void method2() throws Exception {
String str = null;
try {
System.out.println(str.toString());
} catch (NullPointerException e) {
System.out.println(e.getMessage());
throw new Exception("다시 생성한 예외");
}
}
public static void main(String[] args) {
try {
method1();
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
enum BankExpCode {NOT_ACC, EXIST_ACC, LACK_BLNC, NOT_DEPOSIT, MAIN_MENU, ACC_MENU};
class AccountException extends Exception {
// 계좌번호가 틀린 경우
// 계좌번호 중복 생성되는 경우
// 잔액이 부족한 경우
// 입금액이 잘못된 경우
// 메뉴: 0-5까지만 선택 가능
// 서브메뉴: 1,2만 선택 가능
BankExpCode errCode;
public AccountException() {
super("계좌 오류");
}
public AccountException(String message) {
super(message);
}
public AccountException(String message, BankExpCode errCode) {
super(message);
this.errCode = errCode;
}
public AccountException(BankExpCode errCode) {
super("계좌 오류");
this.errCode = errCode;
}
@Override
public String getMessage() {
String msg = super.getMessage();
switch(errCode) {
case NOT_ACC: msg += ": 계좌번호가 틀립니다."; break;
case EXIST_ACC: msg += ": 이미 존재하는 계좌번호입니다."; break;
case LACK_BLNC: msg += ": 계좌의 잔액이 부족합니다."; break;
case NOT_DEPOSIT: msg += ": 입금액이 잘못되었습니다."; break;
case MAIN_MENU: msg += ": 0 - 5만 선택 가능합니다."; break;
case ACC_MENU: msg += ": 1, 2만 선택 가능합니다."; break;
}
return msg;
}
}
throw
키워드로 예외를 떠넘긴다.try
-catch
를 통해 예외 처리를 해준다.catch
문에서 예외 메시지를 출력하려면 예외 메시지를 갖는 생성자를 이용해야 한다.public class AccountExceptionTest {
public static void errNotAcc() throws AccountException {
throw new AccountException(BankExpCode.NOT_ACC);
}
public static void errExistAcc() throws AccountException {
throw new AccountException(BankExpCode.EXIST_ACC);
}
public static void main(String[] args) {
try {
errExistAcc();
} catch (AccountException e) {
System.out.println(e.getMessage());
}
}
}
Exception
클래스를 상속받으므로 Exception
이 갖고 있는 메소드를 호출할 수 있따.getMessage()
웹에서보다 안드로이드 개발 시에 멀티 스레드가 특히 더 필요하다.
main()
메소드를 실행하면서 시작!return
문을 만났을 때스레드.start()
'로 작업 스레드의 run()
메소드 실행import java.awt.Toolkit;
public class BeepTask implements Runnable { // 다른 클래스의 기능을 상속받을 수 있다
@Override
public void run() {
Toolkit toolkit = Toolkit.getDefaultToolkit();
for(int i=0; i<5; i++) {
toolkit.beep();
try { Thread.sleep(500); } catch(Exception e) {}
}
}
}
import java.awt.Toolkit;
public class BeepThread extends Thread { // 다른 클래스의 기능을 상속받을 수 없음(단일상속만 가능하기 때문)
@Override
public void run() {
Toolkit toolkit = Toolkit.getDefaultToolkit();
for(int i=0; i<5; i++) {
toolkit.beep();
try { Thread.sleep(500); } catch(Exception e) {}
}
}
}
Thread-n
으로 설정public class ThreadA extends Thread {
public ThreadA() {
setName("ThreadA"); // 스레드 이름 명명하기
}
@Override
public void run() {
for(int i=0; i<2; i++) {
System.out.println(getName() + "가 출력한 내용"); // 스레드 이름 가져오기
}
}
}
👉 스레드의 갯수가 코어의 수보다 많을 경우, 스레드를 어떤 순서로 동시에 실행할지 결정하는 것
run()
메소드를 조금씩 실행한다.thread.setPriority()
이용)공유 객체를 사용할 때 주의할 점
멀티 스레드가 하나의 객체를 공유해서 생기는 오류
예) 한 사람이 계좌에서 돈을 빼내는데 동시에 다른 사람이 같은 계좌에 돈을 넣으려고 할 때
한 스레드가 설정한 값을 다른 스레드가 그 사이 바꾸면 오류가 날 수도 있다.
👉 그래서 동기화 메소드와 동기화 블록을 사용한다!
단 하나의 스레드만 실행할 수 있는 메소드 또는 블록
synchronized
: 메소드 선언부 또는 메소드 내부에서 블록 선언 시 사용하는 키워드public synchronized void method() {
// 단 하나의 스레드만 실행
}
public void method() {
// 여러 스레드 실행 가능 영역
synchronized(this) {
// 단 하나의 스레드만 실행
}
// 여러 스레드 실행 가능 영역
}
start()
➡ 실행 대기 ⬅(반복)➡ 실행 ➡ 종료