내장형 하드웨어/JAVA

JAVA - 예외의 전파(Exception propagation), Throwable class, 그래픽(Graphics)

동화다아아 2011. 12. 22. 13:48
- Propagation은 AI 쪽에서도 쓰인다.
 → 첫번째 효과가 전파되는 것(나비효과)
 → Exception 처리를 하지 않으면 계속 상위로 영향을 미친다.
 → 즉, 예외 발생시 catch 처리되지 않으면 해당 클래스를 호출한 쪽에 전파된다.
 → 이것은 main 메소드를 거쳐 마지막에는 자바 가상머신까지 간다.
 → 결국 try, catch 를 사용하지 않으면 자바 가상머신이 예외를 처리한다.
 → 예제
// 예외 처리가 호출자에게 전파되는 프로그램
public
 class DivisionByZero
{
  public static void main(String[] args)
  {
    int doubleA = 9;
    int doubleB = 0;

    System.out.println("enter main");
    DivisionClass division = new DivisionClass();
    division.one(doubleA, doubleB);
    System.out.println("exit main");
  }
}
class DivisionClass
{
  public int one(int numberA, int numberB)
  {
    int result = 0;
    System.out.println("  enter one");
    try
    {
      result = two(numberA, numberB);
    }
    catch(ArithmeticException exp)
    {
      System.out.println("    ***catch in one");
    }
    finally
    {
      System.out.println("  exit one");
      return result;
    }
  }
  public int two(int numberA, int numberB)
  {
    int result;
    System.out.println("  enter two");
    result = three(numberA, numberB);
    System.out.println("  exit two");
    return result;
  }
  public int three(int numberA, int numberB)
  {
    int result;
    System.out.println("  enter three");
    result = numberA / numberB; // 예외 발생
    System.out.println(result + "  exit three");
    return result;
  }
}

 → 실행결과

 → 이는 9/0이 예외가 되어 
 → System.out.println(result + "  exit three");
 → System.out.println("  exit two");
 → 이하가 실행되지 않았기 때문이다.
 → 만약 9/1로 int doubleB의 값을 1로 준다면,

 → 처럼 정상적인 동작을 한다.
 → 즉, three 메소드에서 예외가 발생되었으나 catch로 처리되지 않았기 때문에 two()로 전파되었고, 
 → two()에서도 역시 처리되지 않았으므로 one()으로 전파되어 one()에서 예외 처리 된 것을 확인할 수 있다.


- 메소드의 Exception throws
 → 예외를 처리하지 않고 싶은 경우에는 메소드의 표제부에 throws 절을 넣어 메소드가 예외를 던지도록 한다.
 → public static void main(String[] args) throws IOException
  -> IOException 처리를 버리겠다.(가상머신이 처리하도록 해라)
  -> 우리가 만드는 메소드에 위와 같은 방법을 사용할 수 있다.
 → throws는 계속해서 던진 수 있다.
  -> 취해야 할 조치가 명확할 경우에는 try문을 사용한다.
  -> 명확하지 않으면 throws를 사용한다.


- Throwable 클래스
 → Throwable 클래스는 Error 클래스와  Exception 클래스의 수퍼 클래스이다.
 → 두개의 메소드 생성자를 가진다.(인수가 없는 디폴트 생성자, String을 인수로 하는 생성자)
 → Throwable 클래스의 객체는 예외가 발생하는 실행 스택(execution stack)의 레코드를 가진다.
 → 실행 스택 레코드에는 예외가 발생한 프로그램의 위치(line number)와 예외가 발생한 메소드의 호출자들의 이름이 순서대로 들어있다.

 → Throwable 클래스의 메소드
  -> String getMessage()
      : Exception 객체가 가지고 있는 메시지를 반환한다. 메시지는 예외객체의 클래스 이름과 예외에 관한 간단한 설명으로 구성된다.
  -> void printStackTrace()
      : Exception 객체의 메시지와 실행 스택의 내용을 표준 오류 스트림으로 출력
 → 예제
// printStackTrace() 메소드를 이용하여 실행 스택을 검색하는 프로그램
public
 class DivisionByZero3 
{
  public static void main (String[] args) 
  {
    int doubleA = 9;
    int doubleB = 0;      
    System.out.println ("enter main");
    DivisionClass division = new DivisionClass();
    division.one (doubleA, doubleB);
    System.out.println ("exit main");
  }

class DivisionClass 
{
  public int one (int numberA, int numberB) 
  {
    int result = 0;
    System.out.println ("   enter one");
    try 
    {
      result = two (numberA, numberB);
    } 
    catch (ArithmeticException exp) 
    {
      System.out.println ("catch in one\n");
      System.out.println ("Message : " + exp.getMessage());
      System.out.println ("\nStack Trace: "); // stack의 정보를 출력한다.
      exp.printStackTrace(); // stack 구조가 출력된다.
    } 
    finally
    {
      System.out.println ("\n   exit one");
      return result;
    }
  } 
  public int two (int numberA, int numberB) 
  {
    int result;      
    System.out.println ("      enter two");
    result = three (numberA, numberB);
    System.out.println ("      exit two");
    return result;
  } 
  public int three (int numberA, int numberB) 
  {
    int result;      
    System.out.println ("         enter three");
    result = numberA / numberB;
    System.out.println (result + "         exit three");
    return result;
  }
}

 → 실행 결과


 
- 예외의 재발사(Rethrowing Exception)
 → try 블럭에서 발생한 예외를 상황에 따라서 호출자 쪽으로 알려야 할 경우 
 →
예를 들면 예외가 발생시 호출자 쪽에서 프로그램의 실행을 중단시킨다든지, 예외에 대해서 적절한 대응 조처를 취할 경우이다. 
 → 이 경우에는 catch 블럭에서 예외를 재발사하여 호출자에게 예외발생 통보한다.
// 사용자 예외 클래스를 정의한 프로그램
import
 java.lang.Exception;

class MyException extends Throwable
{
  public MyException()
  {
  }// default 생성자
  public MyException(String myMessage)
  {
    super(myMessage);
  }
}
public class ExceptionTestClassA
{
  public static void main(String[] args)
  {
    int a=10;
    int b=5;
    try
    {
      System.out.println("execution in try clause");
      if(a > b) // b가 작을때 예외를 인위적으로 생성한다.
      {
        // MyException 객체를 만들어 강제로 예외를 던졌다.
        // 즉, 무조건 여기서 예외가 걸려 catch가 실행된다.
        throw new MyException("throw an Exception.");
      }    
    }
    catch(MyException exp)
    {
      System.out.println("MyException is cautch.");
    }
    System.out.println("a : " + a + "\tb : " + b);
  }
}

 → 실행 결과


- 그래픽(Graphics)
 → Graphics 클래스는 java.awt 패키지에 정의되어 직선, 사각형, 다각형 등의 도형을 그리는 메소드를 지원하고 화면의 색이나 문자의 폰트등을 관리할 수 있는 메소드를 가지고 있다.
 → Graphics 클래스의 객체는 그림을 그리는 영역을 나타낸다. (예로 애플릿 윈도우는 하나의 Graphic 객체를 가지고 있다.)
 → 애플릿 윈도우에 그림을 그릴 때는 애플릿에 연계된 이 Graphics 객체를 통하여 이루어 진다.
 → 그리기 위한 정보에는 항상 context가 필요하다.
 → 그리기는 Graphics 객체에 정의된 Graphics context를 통해 수행된다.
 → getGraphics() 메소드는 WINAPI의 getDC와 같다.
 → drawString()의 정의 - 문자열을 출력해 준다.

 → 예제(템플릿이므로 html로 실행시킬 소스도 필요하다.)
// ShowDrawString.java
// 문자열을 출력하는 애플릿 프로그램
import
 java.applet.Applet;
import java.awt.*;

public class ShowDrawString extends Applet
{
  public void paint(Graphics g)
  {
    g.drawString("drawString() draw this string."2020);
  }
}


// ShowDrawString.html
<HTML>
<HEAD>
<TITLE> ShowDrawString </TITLE>
</HEAD>
<BODY>
<P>This page showes java applet!
<APPLET CODE = "ShowDrawString"  WIDTH = 300 HEIGHT = 30> </APPLET>
Now the end of body
</BODY>
</HTML>
 → 실행해 보면

 → 와 같이 브라우저에서 출력된다.

 → 윈도우 생성 테스트 예제
// Frame 클래스로부터 윈도우를 생성하는 프로그램
import
 java.awt.*;
import java.awt.event.*;

public class MakingWindow extends Frame
{
  public MakingWindow()
  {
    super("Making Window");
  }
  // dos는 그래픽 객체가 없어서 창을 띄울수 없느나
  // Java는 그래픽 객체를 만들 수 있다.
  public static void main(String[] args)
  {
    MakingWindow w = new MakingWindow();
    w.addWindowListener (new WindowHandler());
    w.setBounds(150130400350);
    w.setVisible(true);
  }
  public void paint(Graphics g)
  {
    g.drawString("This is thd first Application Window"5050);
  }
}
class WindowHandler extends WindowAdapter
{
  public void windowClosing(WindowEvent e)
  {
    System.exit(0);
  }
}
 
 → 실행 결과