220112 예외처리-throws , Thread
***예외Exception처리***
교재 10장, 4시부터 반드시 강조한 예외처리 부분.. 설명 다시 듣기
: 예외란 프로그램이 실행되는 동안에 발생하는 예기치 못한 에러를 의미하고, 예외처리란 이런비정상적인 종료를 막기 위해서 사용하는 것
※에러와 예외의 차이
에러: 하드웨어의 잘못된 동작 또는 고장에 의한 오류, 에러 발생시 프로그램 종료, 정상 실행 상태로 돌아갈 수 없음
예외: 사용자의 잘못된 조작 또는 개발자의 잘못된 코딩에 의한 오류, 예외 발생시 프로그램 종료, 예외 처리 추가하면 정상 실행 상태로 돌아갈 수 있음
주로 사용하는 곳
1 주로 파일 입출력 처리할 때 반드시 예외처리를 함(특정 파일을 열거나, 읽거나, 저장할 때 등)
java.io.* 패키지의 클래스들을 이용해야 할 때는 파일, 값 등을 이용할 때 반드시! 필수적으로! 필요한 것!
2 Database 연결, 연동을 수행할 때,
java.sql.* 패키지 이용할 때! 반드시 예외처리 함!
-> 안 그러면 형식상으로 오류가 발생해 컴파일 안 됨... 꼭.. 배워서 활용해야 함!
해야 하는 이유---> 프로그램을 안전하게 실행, 종료시키기 위해! 비정상적으로 멈추지 않게 하려고!
*예외Exception의 종류
일반 예외: 예외처리 코드 없으면 컴파일 오류
실행 예외: 예외처리 코드를 생략해도 컴파일되는 예외
1. 일반 Catch (DivideZeroExceptionHandling.java 참고)
try{
예외가 발생할 '가능성'이 있는 문장; //예외 발생하지 않았을 때는 try 내부 코드만 실행
}catch(예외클래스명 매개변수){ //예외 발생시 try에서 예외 발생한 코드부터 그 아래는 실행되지 않고 catch로 넘어가 catch 코드 실행
예외 메시지;
}
Q.어떤 예외클래스를 catch에 넣어야 하나요?
A. 일단 예외를 발생시켜보면 뭘 넣어야 할지 알 수 있을 겁니다
농담임
catch ( Exception e ) {
a = 2;
c = b/a;
}
예외 중 최상위super 클래스인 Exception 클래스를 넣으면 모든 예외 커버 가능함
Q. Catch문에 예외클래스와 매개변수.. 매개변수 굳이 왜 쓰죠?
A. 당연히 예외 클래스의 메소드를 객체를 이용해 가져와 사용하기 위해서임
e.printStackTrace(); -> 예외 정보를 자세히 출력시킴
(얘는 s.o.p 안에 사용하면 안됨 값 하나 리턴하는게 아니라 void로 출력까지 한꺼번에 해주거든)
e.getMessage() -> 예외 정보 문자열로 반환 // 얘는 s.o.p 가능
e.toString() -> 예외의 간단한 설명문 반환 // 얘도
ex) ArithmeticException : 0으로 나눌때 예외가 발생한 경우
e.getMessage() -> 예외 정보 반환 ---> / by zero 출력
e.toString() -> 설명문 반환 --> java.lang.ArithmeticException: / by zero
e.printStackTrace(); -> 싸그리 싹싹 긁어 싹 출력해줌↓
java.lang.ArithmeticException: / by zero
at p2022_01_11.DivideZeroExceptionHandling2.main(DivideZeroExceptionHandling2.java:13)
2. 다중 catch (MultiExceptionHandling.java 참고)
try{
예외가 발생할 가능성이 있는 문장;
}catch(예외클래스명 매개변수){
예외 메시지;
}catch(예외클래스명 매개변수){
예외 메시지;
}
---> 각자 다른 예외클래스명이 들어가야 함 : 각 예외상황 별로 다른 처리를 할 때라든가 그런 때 사용하는 것
---> try 안에 여러 예외가 존재하는 경우 가장 처음 발생한 예외를 처리하고 이하 아래로는 실행되지 않음
이미지를 보면 알겠지만... 어떤 예외가 위에 있느냐에 따라 다른 catch문이 실행됨 그리고 다른 예외처리는 되지 않고 실행이 종료됨
※Exception은 가장 아래에 넣어야 함
: 모든 예외를 받을 수 있는 최상위 클래스이기 때문에, 다른 catch에 해당하는 오류가 발생하더라도 해당 예외처리가 있는 catch 위에 Exception이 존재하면 그 쪽이 예외를 처리하게 됨 -> 원하는 예외처리를 할 수 없게 되겠지
그러니까 아예 모든 오류 케이스 지나고... 해당하는 catch가 없을 경우 그때 Exception이 동작할 수 있도록 해야 함-> 가장 마지막에 배치하기!
ExceptionEx3.java 참고 int var=50; try{ int data=Integer.parseInt(args[0]); //args[0]=null -> 변환 자체가 불가능-> Exception //args[0]="5"; -> String형 5가 Integer로 int 5가 됨-> 예외 발생 안 함 //args[0]="a"; -> String형 a는 int형으로 변환할 수 없음 -> NumberFormatException //args[0]="0"; -> int형으로 변환은 되지만 0은 분모가 될수 없어 -> ArithmeticException System.out.println(var/data); //문제 없으면 이거 출력되고 try 빠져나옴 }catch(NumberFormatException ne){ System.out.println("숫자가 아닙니다."); }catch(ArithmeticException ae){ System.out.println("분모는 0이 될 수 없다."); }catch(Exception e){ System.out.println("Exception"); } |
3. catch-finally (MultiExceptionHandling1.java)
try{
예외가 발생할 가능성이 있는 문장;
}catch(예외클래스명 매개변수){
예외 메시지;
}finally{
//주로 파일을 닫을 때, 데이터베이스 연결 끊을 때 사용
// 예외 발생 여부와 관계없이 무조건 실행;
}
4. throws
:한개의 클래스에 동일 형식으로 이루어진 다수의 메소드가 있는데, 그 메소드들에 대한 예외처리를 하고 싶을 때 -> 어차피 예외가 발생한다면 다 같은 예외일 테니까 try 하나로 묶어 사용한다고 생각하면 될듯..
방법은
예외처리하려는 메소드명 뒤에 'throws 예외클래스명' 을 붙임-> try에 예외처리하고싶은 메소드를 호출시키고-> 메소드에서 예외가 발생한다면 catch로 넘어가 그 예외처리를 실행하게 됨
=====> 즉, 그 메소드를 호출한 곳으로 예외처리를 양도해서 거기서 처리하도록 하는거지!
class Test{
public void check() throws Exception{
}
public static void main(String[] args){
try{
Test t = new Test();
// 같은 클래스에 존재하는 메소드여도 main에 불러올때는 클래스 객체를 선언해서 메소드를 호출해야 하더라
//만약 호출하고 싶은 메소드가 static이라면 클래스명 생략해도 가능하긴 한데 보통은 그렇지 않으니까 꼭 클래스 객체 선언해서 메소드 호출시킬 수 있도록 해야함. 주의!
//그렇게 메소드 실행되고 문제 발생하면 catch로 돌아옴
////////근데, 메소드 실행 과정에 다른 메소드 호출시키는게 있고 그 다른 메소드에서 예외가 발생한다면, 그리고 그 다른 메소드에도 throws 처리가 되어있다면, 여전히 catch로 처리 가능함
//throws 가 붙어있다면 그게 뭐든! 메소드 호출에 엮여있기만 하면! catch에서 예외처리 할 수 있더라!!
t.check();
}catch(Exception e){
}
}
}
+) 메소드를 throws ArithmeticException 으로 넘기고 catch에 Exception 들어가는 건 괜찮음
생긴 예외가 Exception 안에 포함된 거니까 얘가 다 처리 가능함
근데 throws Exception으로 넘기고 catch ArithmeticException 는 안됨
Exception이 꼭 ArithmeticException일 거라는 보장은 없기 때문에~
5. 강제 예외 발생 (ThrowException.java 참고)
- for문으로 배열을 출력하거나 할 때, 루프의 대다수는 예외가 없을것이고 뒤로 가면서 예외가 발생할 수 있을 것임. 이럴 때 예외가 발생하게 될 그 조건을 미리 달아놓고 new 연산자로 예외처리 객체를 만들어, 그 조건에 해당되는 순간 catch로 예외를 던져(throw) 처리하게 만드는 그런 과정인듯함
--> 근데 사실 문제가 생기는 조건에선 throws가 있으니까 catch로 넘어가긴 하거든... 내가 보기엔 예외가 발생하지 않는 부분에서 예외 메시지가 뜨게 한다거나 그런 때? 유용하게 쓸 수 있는 것 같애 이 범위를 조절할 수 있다는게 가장 큰 장점이지 않을지??
ex) int[] intA={1,2,3,4};
일 때 intA[i]를 출력한다고 하면, i=4일 때 exception이 발생하겠지
근데 만약 i=3이라는 조건에 throw new Exception(); 을 달아둔다면
원래라면 문제없을 intA[3]값이 출력되지 않고 예외로 판단되어서 catch의 예외처리로 넘어가게 되는 거지
class Test{
public void check() throws ArrayIndexOutOfBoundsException {
for( int i=0 ; i<10 ; i++ ) {
// 예외를 던짐(프로그래머가 예외를 발생시킴)
if( i == 3 ){
throw new ArrayIndexOutOfBoundsException();
//특정 조건 만족하면 new 연산자로 예외처리 객체 생성
//--> 강제로 특정 조건을 예외로 만들어서 원하는 메시지를 출력할 수 있도록 제어하는 것
(throw new XXXException("메시지"); 형태도 가능함---- 얘넨 s 안붙음 주의)
}
}
}
public static void main( String[] args ) {
Test t = new Test();
try {
t.check(); // 위에 저거.. i==3이면 예외 발생하는 조건 달린 메소드 호출
} catch ( ArrayIndexOutOfBoundsException ab ) {
ab.printStackTrace();
}
}
6. 사용자 정의 예외 (UserExceptionTest.java)
: 사용자가 자바 표준 API에서 제공하지 않는 예외를 발생시키고자 할 때 사용
public void printNumber() throws UserDefineException {
for( int i=0 ; i<10 ; i++ ) {
// Excpetion을 발생시킴
// if( i == 3 ) throw new UserDefineException();
//메시지를 따로 지정해주지 않을 때는 기본생성자 사용하면 됨
if( i == 5 ) throw new UserDefineException( "사용자가 정의한 Exception" );
// super( information ); 여기 infomation으로 ↑이게 넘어가게 되고 예외에서 메시지로 출력될 것
// 예를 들어 ArithmeticException 예외 발생 시 getMessage() 메소드를 쓰면 / by zero가 출력되잖아 그런 메시지를 만들어준거지
System.out.println( i );
}
}
public class UserDefineException extends Exception { //슈퍼클래스 상속 필수
public UserDefineException() {
} //기본생성자 -> 따로 예외 정보 지정 안 해줄때
public UserDefineException( String information ) {
// (자기 부모클래스) Exception 클래스의 생성자 호출
// super는 상속관계에 있는 부모클래스=Exception
super( information );
}
}
------------------------------
main 메소드에서 try catch 예외처리할 때
catch ( UserDefineException ue ) {
System.out.println( ue.toString() );
//UserDefineException이 Exception을 상속한 상태니까 toString 쓸 수 있고
//toString으로 반환하는 메시지 -> 위에서 생성자 매개변수로 메시지 만들어서 넘기고 넘긴게 또 super(information)으로 Exception 생성자 호출할때 그대로 넘어감-> UserDefineException 예외가 발생하면 해당하는 메시지가 toString() 메소드를 통해 출력되는 흐름이 된다
}
* 예외 클래스
ArithmeticException : 0으로 나눌때
-> DivideZeroException어쩌고.java 확인
ArrayIndexOutOfBoundsException : 배열의 범위를 벗어났을때
NumberFormatException : 숫자외의 값을 사용할때
NullPointerException : 객체를 생성하지 않고 멤버변수나 메소드를 호출할때
IOException : 입출력에 관련된 예외
FileNotFoundException : 파일이 없을때 발생
SQLException : 데이터베이스 관련 예외
***Thread***
게임, 채팅 등 특정 프로그램을 다룰 때 사용하는? thread 이용해 socket 통신 (java.net.*)
교재 12장
: 한 개의 process를 구성하는 작업 단위
(process: 주기억장치(ram)에서 실행 중인 하나의 program)
동시에 여러가지 작업을 해야 하는 경우 보통 사용됨 -> 쪼개고 쪼개서 여러 작업 파바바박 왔다갔다 하면서 동시에 되는것처럼 보이게... 하는거지
* 스레드 생성 방법
-Thread Class
: Thread 하위 클래스로부터 생성 -> Thread 상속 후 run() 메소드 오버라이딩(재정의)
ThreadEnd.java
public class ThreadEnd extends Thread { //java.lang이라 import ㄴㄴ
public void run() { //run메소드 재정의
// thread가 시작되면 실행되는 문장
for( int i=1 ; i<=20 ; i++ ) {
System.out.println( "run number = " + i );
}
}
public static void main( String[] args ) {
ThreadEnd tt = new ThreadEnd();
// thread를 실행시킴
tt.start(); //-> 실행 가능한 상태= Runnable 상태
//overriding된 run() 메소드를 호출!
//이때 run()은 실행중인 상태가 됨
for( int i=101 ; i<=120 ; i++ ) {
System.out.println( "-------> main number = " + i );
}
//얘랑 저 위에 thread랑 둘다 실행되면서 서로 엎치락뒤치락.. 순서 왔다갔다 하면서 아무튼 동시에 실행됨
}
- Runnable Interface
: Runnable을 상속받는 구현 클래스에서 run() 메소드 오버라이딩 후, (추상이라 필수임)
main에 구현 클래스의 객체를 생성해, Thread 클래스의 생성자 매개변수로 집어넣음
RunnableTest.java
// Runnable을 상속받는 클래스의 객체 생성
RunnableTest tt = new RunnableTest();
// Thread 클래스 객체 생성
Thread t = new Thread( tt ); //Runnable을 매개변수로-> run() 넘김
// Thread를 시작시킴
t.start(); //Runnable의 tt.start()가 아니고 Thread의 start()임 (주의!)
-> Thread Class보다 중간에 한단계가 더 있는거지 run() 오버라이딩을 Thread가 아니라 Runnable을 통해 해서~ Thread로 넘겨서~ Thread가 실행시키는 과정이라고 봐야,..
* Thread의 생명 주기(Life Cycle)
Runnable : 새로 생성한 Thread를 start하면 Runnable 상태가 됨.
실행 가능한 상태( start() 메소드 호출한 상태)
Running : CPU를 점유하고 run() 메소드 내의 명령문을 실행하는 상태.
실행상태(run() 메소드를 실행한 상태)
Block : 특정 메소드의 호출에 의해서 현재 실행중인 Thread가 CPU의 제어권을 잃어버린 상태.
(-> 우선순위가 높은것 먼저 실행된다거나) -> terminated 상태?
-------> 멀티 태스팅인 경우 Running-Block 반복됨
Dead : run() 메소드의 명령 수행이 끝났을 경우
* Multi Tasking
: 두가지 이상의 작업을 동시에 처리하는것
- 멀티 프로세스: 독립적으로 프로그램을 n개 실행하고 각자 작업 처리
- 멀티 스레드: 한개의 프로그램을 실행하고 그 내부에서 여러 작업 처리
*자바의 스레드 스케줄링
: 우선순위(Priority) 방식- 우선순위 높은 스레드가 실행 상태 더 많이 가지도록, 1~10까지, 기본(NORM)은 5
//필드에 MAX_PRIORITY MIN,NORM 이런거 있고.. 여러개 만들때 이걸로 우선순위 지정해줌
: 순환 할당 방식- 시간 할당량Time Slice 정해 하나의 스레드를 그 시간만큼 실행 (단, 코드로 제어 불가능)