Compile Unchecked Exception 계열(RuntimeException 계열) 로 구분됨
< 기본 문법 >
try { // 예외가 발생할 것으로 예상되는 범위의 코드들... // ⇒ 예외 발생 코드 아래쪽의 나머지 try 블록 코드들은 실행되지 못함 } catch(예외클래스명 변수명) { // 예외클래스에 해당하는 예외 발생 시 처리할 코드들... } finally { // 예외 발생 여부와 관계없이 무조건 실행할 문장들... // (ex. DB 자원 반환, I/O 자원 반환 등) }
체크예외 : Exception 클래스의 서브클래스이면서 RuntimeException 클래스를 상속하지 않은 것들
언체크예외 : RuntimeException을 상속한 클래스
< Compile Checked Exception 계열 : 실행 시점에서 오류 >
나눗셈 피연산자가 0인 경우 ArithmeticException 예외 발생
배열에 존재하지 않는 인덱스 접근 시 ArrayIndexOutOfBoundsException 발생
객체를 저장하고 있지 않은(null) 참조변수에 접근 시 NullPointerException 발생
⇒ 전부 문법적 오류는 없는데 실행하면 오류남! (실행하기 전에는 오류 티가 안난다!)
try 구문이 없을 땐
out.println에 적어 준 “프로그램 종료!” 문구가 안뜬다!
⇒ 정상적인 종료가 안되서 저 코드까지 실행이 안됨
try 구문에 넣어줬을 때 실행창 : try ~ catch 문인데 오류창을 잘 보면 catch가 아니라 finally를 추가하라고 뜸
왜??? 사실 catch는 필수가 아니다! 근데 왜 catch를 쓰느냐
finally만 써도 되지만 그렇게 하면 예외가 발생했는지 안했는지도 모름! (디테일하게 알 수 없다)
* 예외를 처리하는 방법
예외를 직접 적어줌 : XXXException
runtime Exception을 적어줌
모든 예외 통칭 : 그냥 Exception 이라고 적어줌
0으로 나누었기 때문에 예외 발생!
< e.getMessage(); >
예외 발생 시 전달받은 원인 메세지 리턴
에러 이벤트와 함께 들어오는 메세지를 출력
리턴타입 String
< e.printStackTrace(); >
예외 발생 상황에 대한 정보(예외 클래스명, 메세지, 발생 위치 출력)
에러 메세지의 발생 근원지를 찾아서 단계별로 에러를 출력
리턴타입 Void
상세한 위치까지 알려줌(클릭하면 위치로 이동)
이런식으로 예외가 두 번 발생할때는 어떻게 될까? (+배열 인덱스 3번은 없음 : 예외)
출력해보면 0으로 나눈 부분의 예외만 나오고 뒷 부분(배열 인덱스 예외)은 안나온다.
⇒ 예외 발생 코드 아래쪽의 나머지 try 블록 코드들은 실행되지 못함
뒷부분도 예외처리 되는 지 앞부분 예외 주석처리 해보기
출력해보면 예외문구가 나온다.
뒤에 out.println을 추가 해도 출력창 똑같이 나옴(out.println 부분은 예외 발생 뒷부분이라 실행조차 안됨)
> 이렇게 예외가 2번 발생할 땐 그럼 어떻게 해야할까?
catch 문을 하나 더 추가해서 다중처리가 가능하다!!
catch문을 2번 사용하여 0으로 나눴을때의 예외처리와 배열 인덱스 예외 처리를 나눠서 적어줌.
e.getMessage(); 로 출력해보면 이렇게 인덱스 ‘3’이 틀린 걸 알수 있다!
위에서 처리하지 못하는 나머지 예외들을
Exception 클래스로 모두 한꺼번에 처리 가능(업캐스팅에 의한 객체 전달)
위에 이미 Exception 클래스로 전부 처리했기 때문에 뒤에 더이상 추가 안됨(오류!)
if 문이랑 똑같이 순차적으로 진행된다.
⇒ Exception 예외 처리 아래쪽에 다른 예외 클래스 지정 불가능
if문과 마찬가지로 위에서부터 차례대로 체크하므로 하위클래스부터 상위클래스 순으로 예외 처리 필수!
======== Ex2.java
Alt + Shift + Z (try~catch문 단축키)
finally 가 없어도 예외처리 상관없이 “프로그램 끝!” 이라는 글자가 나온다
근데 우리는 왜 finally 를 써야할까?
> finally 도 예외처리 상관없이 실행하는 문장들을 적는 곳
“프로그램 끝2”는 출력되지 않음!
만들어 둔 메서드()를 try~catch문으로 감싸기
다시 실행해보면 끝까지 출력 잘 됨.
try 문 안에 if문 넣어서 num이 0이 아닐 경우 return 해주기
“메서드 끝”은 출력이 안되는데, finally 는 나와!
분명 return 때문에 뒷쪽이 실행이 안되는데 finally 는 무조건 실행됨!
return 문에 의해 현재 메서드를 종료하고 돌아가야하므로 아래쪽 try 블록 내의 문장은 물론 try 블록 바깥의 문장도 실행 X
⇒ 그러나! finally 블록 내의 문장은 실행 후에 리턴됨
리턴시점해서 실행이 되느냐 여부! 331p
======== Ex3.java
342p
3을 0으로 나누었기 때문에 예외 발생!
try~catch 쓰면 오류 없이 나옴
근데 우리가 할 건 (대리가 처리하는)이거 말고 예외 위임!!
예외가 한 눈에 보이게 바꾸기 (“클래스”라는 게 없어서 예외)
예외를 넘겨줌! 대리 내부에 있던 빨간 밑줄 없어지고 팀장()메서드 안에 밑줄 생김
이렇게 (팀장이)대신 예외 처리 가능!
팀장도 예외처리 하기 싫다면 또 위임하면 됨!
이제 main() 으로 예외처리 넘어감! (throws)
⇒ main() 에서는 더이상 위임할 곳이 없기 때문에 최종적으로 main() 에서 처리해야함
(main() 에서도 throws 를 할 수는 있는데… 처리할 곳이 없다!)
⇒ 팀장() 으로부터 예외를 위임받은 곳이 main() 메서드 일 경우 더 이상 위임할 곳이 없으므로 최종적으로 main() 메서드에서 예외 처리 필요! 343p
350
======== Ex4,java
우리는 이런식으로 만들어옴!
이렇게 만들면 개발자들은 출력창으로 알 수 있지만 사용자 입장에서는 185를 입력하는 순간 오류가 발생하는 걸 모른다!
예외 처리 하라고 나옴!
근데 우리가 예외처리 할 게 아니라 사용자에게 알려주고싶다
→ 예외 처리 위임! throws! 던진다!
main() 에서 예외 처리
이런식으로 구체적인 오류 상황을 알려줄 수 있다!
→ 여기까진 사용자정의 클래스 만든거 아님!
======== Ex5.java
< 사용자 정의 예외 클래스 >
기존의 API 에서 제공하는 클래스 외에 별도의 예외를 처리하는 클래스
주로 Exception 클래스를 상속받아 정의
슈퍼클래스로부터 받아오는건 Alt + Shift + S → C
String 만 받아오면 됨
이렇게 자동으로 만들어짐
enum 타입 : ID, Password 중 실패한 항목을 저장할 enum 객체
enum 을 만들면 ID가 틀렸을 때와, pass 틀렸을 때 구분이 가능하다
Alt + Shift + S → R ⇒ 이렇게 getMessage() 바로 가져와도 됨
그러나 getLocalizedMessage() 메서드 오버라이딩
이런식으로 만들어줌
아이디와 패스워드 틀린 거 구분 가능!
이거 못한다고 코드 못짜는 건 아니지만 좀 더 디테일함을 위해 배우는 거!
이 부분은 안외워도, 몰라도 상관없다
main() 밖에 만들기
main() 에서 호출
isLogin() {}
throw 추가 (throws 아님 주의!)
여기 오류를 해결하려면 여기서 예외처리 하든가
main() 으로 throws 해주던가
우린 main()으로 넘김! throws!
실행창 : 아이디 틀림!
이렇게 하면 코드가 길어지지만 정형화된 문제메세지를 띄워준다…. 귀찮….
코드 길이 측면에서는 좋은 방법이 아니지만 우리가 원하는 형태로 예외 개조 가능!
필수 아닙니다~~! 알아두면 고급진… 프로그래밍 가능…...ㅎ
그렇지만 throw 와 throws 키워드★는 알아두기! (용도 구분하기!)
542 멀티스레드
Ctrl Shift Esc 작업관리자
======== Ex6.java
< 쓰레드(Thread) >
하나의 프로세스 내에서 자원을 공유하는 최소 실행단위
두 개 이상의 쓰레드가 동작하는 것을 멀티쓰레딩(Multi Threading) 이라고 함
멀티 쓰레딩 구현 방법
1) Thread 클래스를 상속받아 구현
2) Runnable 인터페이스를 상속받아 구현
서브클래스에서 run() 메서드를 오버라이딩하여 멀티쓰레딩으로 처리할 코드를 기술하고, Thread 클래스의 start() 메서드를 호출하여 멀티쓰레딩을 수행
class Ex6() 바깥에 만들기
메인에서 인스턴스 생성 후 실행해보기
A작업 처리 → B작업 처리 → C작업 처리 순서대로 됨
⇒ 이런 방식은 단일 쓰레드 (우리가 지금까지 하던 방식)
> 멀티쓰레드
멀티 쓰레드 만들어보기 (가장 간단한 쓰레드 클래스 상속)
쓰레드 클래스는 java.lang 패키지라 별도의 Import가 필요 없음
Alt + Shift + S → V 해서 run() 오버라이딩
이렇게 똑같이 만든다!
main() 에서 인스턴스 3개 만들어서 실행해보기
근데 실행해보면 단일쓰레드의 실행과 똑같이 A작업 처리 → B작업 처리 → C작업 처리 순서대로 됨
단일메서드랑 다른게 없다!? 왜?
구현은 run()에 하지만 우리는 run()호출이 아니라 start()로 호출해야됨!
(우리가 run()이라고 직접 호출하는게 아님)
XX.start(); ⇒ 조심하기!
이렇게 호출하면 A B C 작업이 섞여서 작업됨! ⇒ 멀티 스레딩!
오버라이딩 한 run() 메서드를 호출하면 멀티쓰레딩이 되지 않는다!
⇒ run() 메서드는 JVM 에 의해 별도로 호출되어야 하는 메서드
======== Ex7.java
멀티쓰레딩 클래스 정의할 때, 이미 다른 클래스를 상속받은 경우 Thread 클래스 상속 불가
⇒ Thread 클래스 대신 Runnable 인터페이스를 구현하는 방법을 사용해야함
인터페이스 상속받아옴
main() 에서 인스턴스 생성해보기
start() 로 호출해보자
호출하려고 하면 이렇게 빨간밑줄 오류남
우리가 상속받은 건 인터페이스! 전부 추상메서드! 호출할 수가 없다.
대신 처리해 줄 무언가가 필요하다…..
이 세 줄이 필요하다!
⇒ 상속 받을 일은 많기 때문에 우린 Thread를 직접 상속받는 것 보다 Runnable을 사용하는게 더 잦을 거…. 우리는 이거 잘 알아둬야 함! Runnable 기억해두기!