Home [Java 프로그래밍] 7강 - 패키지와 예외 처리
Post
Cancel

[Java 프로그래밍] 7강 - 패키지와 예외 처리

💡해당 게시글은 방송통신대학교 김희천 교수님의 'Java 프로그래밍' 강의를 개인 공부 목적으로 메모하였습니다.



학습 개요


  • 패키지는 관련이 있는 클래스나 인터페이스의 묶음으로, 계층 구조로 이루어진 클래스나 인터페이스의 라이브러리임
  • 예외는 실행 중에 발생하는 경미한 오류이며, 예외 처리를 통해 정상 상황으로 복구 될 수 있음
  • 패키지를 정의하고 사용하는 방법과 예외 처리 개념을 이해하고 활용할 수 방법을 익히도록 함



학습 목표


  • 사용자 패키지 정의할 수 있음
  • 정의된 패키지를 사용하여 프로그램 작성할 수 있음
  • 예외의 종류 설명할 수 있음
  • 예외 처리 코드 작성할 수 있음



강의록


패키지

패키지

  • 관련이 있는 클래스와 인터페이스의 묶음
    • 클래스와 인터페이스는 패키지의 멤버로 존재
    • 패키지는 클래스와 인터페이스의 .class 파일이 저장된 폴더
  • 전체적으로 패키지는 계층 구조로 이루어짐
    • 패키지(폴더와 유사) 단위로 계층 적으로 분류됨
  • 패키지의 용도
    • 클래스를 쉽게 찾아 사용하기 위해
    • 클래스의 이름 충돌을 피하기 위해

      1
      
        import graphics.Rectangle
      
      1
      
        import java.awt.Rectangle
      
    • 클래스의 접근 범위를 제어하기 위해

시스템 패키지

  • JDK가 제공하는 클래스 라이브러리
    • JDK와 함께 설치됨
    • 클래스 파일들은 기능에 따라 패키지로 묶여 분류됨
      • 과거에는 jar 파일로 압축되어 있었음
        • ex)

          1
          
            rt.jar
          
      • 최근 버전에는 모듈 단위로 분산 되어 저장되어 있음
    • C:\Program Files\Java\jdk-21\lib\src.zip 에서 소스를 확인할 수도 있음

시스템 패키지의 사용

  • 가장 기본이 되는 최 상위 시스템 패키지는 java패키지
    • 대부분 시스템 패키지는 java.으로 시작
  • Java 프로그램에서 상위 패키지와 하위 패키지의 구분을 위해 도트(.)를 사용
    • ex) java.lang, java.io, java.nio.file, java.util, java.util.stream
    • Java 언어에서 가장 기본적 클래스는 java.lang패키지에 존재
    • 프로그램에서 클래스를 사용할 때는 java.io.IOException과 같이 완전한 이름으로 표현하는 것이 원칙임

사용자 정의 패키지

패키지 정의

1
2
3
4
5
package com.vehicle;

public class Car {
    String szType = "승용차";
}
  • 컴파일 결과로 Car.class 생성
  • Car.class는 com.vehicle패키지에 저장
  • com.vehicle의 위치
    • 컴파일 할 때 -d 옵션 사용하여 지정함
      • ex)

        1
        
          javac Car.java -d D:\javaClasses
        
        • 이 경우 D:\javaClasses\com\vehicle\Car.class
        • 이클립스 에서는 작업공간\프로젝트폴더\bin\com\vehicle\Car.class

Eclipse에서 사용자 패키지 정의하기

  • 메뉴 File → New → Package 선택
    • 패키지에 해당하는 폴더가 만들어짐
    • 생성된 패키지에서 클래스를 만들면 됨
  • 또는 메뉴 File → New → Class 선택하여 클래스 이름과 함께 패키지 이름을 함께 입력함

    Untitled

패키지와 클래스의 사용

  • 다른 패키지에 존재하는 public클래스를 사용하려면 기본적으로 패키지 경로를 포함한 완전한 클래스 이름을 사용해야함
    • 프로그램에서 여러번 사용한다면 import구문 사용하는 게 좋음
  • ex)

    1
    2
    
      graphics.Rectangel myRect = new graphics.Rectangle();
      java.util.Scanner s = new java.util.Scanner(System.in);
    
    1
    2
    3
    4
    5
    6
    7
    8
    
      import java.util.Scanner;
        
      public class Main {
          public static void main(String args[]) {
              Scanner s = new Scanner(System.in);
                    
          }
      }
    
  • import
    • 1개 클래스 또는 패키지에 있는 클래스 전체를 import할 수 있음

      1
      2
      
        import 패키지 이름.클래스 이름;
        import 패키지 이름.*;
      
    • import구문은 소스 코드 맨 앞에 위치함
    • 단, package구문이 있다면 그 다음에 위치함
    • 프로그램에서 패키지 경로를 생략하고, 이름만 가지고 클래스나 인터페이스를 사용할 수 있게 함
  • Java 프로그램에서 import java.lang.*;구문은 자동 포함됨

패키지의 사용과 접근 제어

  • 아래 프로그램에서 package구문이 없다면 패키지 접근 수준의 Car 클래스 사용 불가

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    
      // package com.vehicle;
        
      import com.vehicle.*;
        
      class MyCar extends Car { // 오류 발생
      }
        
      class MyBus extends Bus { // 기본 패키지에 MyBus 클래스 생성
      } 
        
      public class PackageTest {
          public static void main(String args[]) {
              Bus bus = new Bus();
              Car car = new Car(); // 오류 발생
          }
      }
    
    1
    2
    3
    4
    5
    
      package com.vehicle;
        
      class Car {
        
      }
    
    1
    2
    3
    4
    5
    
      package com.vehicle;
        
      public class Bus extends Car {
        
      }
    

클래스 찾기

  • 컴파일하거나 실행할 때, 필요한 클래스(A)를 찾아야함
    • 컴파일러가 A.class가 위치한 경로 또는 A.class를 포함하고 있는 jar 파일의 존재를 알아야 함
  • JVM은 기본 패키지나 확장 패키지 외에 사용자 클래스도 찾을 수 있음
    • 이때 방법이 필요함
  • 컴파일러는 환경 변수 CLASSPATH에 지정된 경로에서 사용자 클래스를 찾을 수 있음
  • 환경 변수 CLASSPATH
    • CLASSPATH의 경로는 jar 파일을 포함할 수 있음
    • ex) 프로그램에서 graphics.Circle클래스를 사용하는 경우
      • CLASSPATH = 경로;a.jar 라고 가정
      • 이때, 경로\graphics\Circle.class 또는 a.jar에 \graphics\Circle.class가 있어야 함
    • 이클립스에서는 프로젝트 폴더 → Properties → Java Build Path → Libraries → Classpath에서 추가함

예외와 예외 처리

예외와 에러

  • 에러(Error)는 실행 중 발생하는 심각한 오류로 더 이상의 실행이 불가함
  • 예외(Exception)는 경미한 오류로 복구 가능함
    • 예외 발생이란 정상적 실행 흐름을 벗어난 예외적 사건이 발생함을 의미
  • 예외 발생과 처리
    • 프로그램 실행 중에 예외 상황이 발생하면,예외 처리 코드에 예외 객체를 생성하여 던짐(throw)
    • 적당한 예외 처리 코드(exception handler)가 있으면 예외 객체를 잡아(catch) 처리한 뒤, 프로그램은 계속 수행 됨
      • 예외 처리 코드가 없으면, 오류 메시지가 출력 되면서 프로그램이 즉시 비정상적으로 종료 됨
    • 예외 객체는 Exception클래스(또는 하위 클래스)로 표현되며 예외 발생 정보를 가지고 있음

예외 클래스의 계층 구조

  • Exception클래스는 Throwable클래스의 자식 클래스
    • toString(), printStackTrace()메소드 등을 상속 받음

    image.png

    • Unchecked Exception
      • 예외 처리 코드 강제성 없음
    • Checked Exception
      • 반드시 예외 처리 코드 필요

예외 처리

  • 예외가 발생했을 때 이 상황을 바로 잡아 계속 수행하도록 하는 것
  • 예외 발생 시, Exception 객체를 생성하고 throw함

    1
    
      throw new MyException();
    
  • throw 된 예외 객체를 예외 처리 코드가 catch하여 예외를 처리함
  • 예외 발생과 처리
    • checked Exception 예외가 발생할 수 있는 경우, 반드시 명시적인 예외 처리가 필요함
      • 예외 처리 코드가 없으면 컴파일 오류
    • RuntimeException예외의 경우, 예외 처리를 안 해도 됨
      • 프로그램을 정확하게 작성하지 않은 경우 발생 됨
      • ArithmeticException, NullpointerException, IndexOutOfBoundsException

예외 처리 방법

  • 직접 처리
    • 예외가 발생한 곳에서 예외 객체를 잡아서 처리하는 것
    • try-catch구문 또는 try-catch-finally구문 사용하여 예외를 처리함
    • 일반 코드와 예외 처리가 분리되어 가독성이 좋아짐
  • 간접 처리(예외의 전파)
    • 예외 발생 가능성이 있는 메소드의 선언에서 괄호 다음에 throws예외 클래스를 사용
      • 해당 메소드는 예외를 발생 시킬 수 있는 메소드
    • 그 메소드를 호출한 메소드에게 예외 처리를 전달 또는 위임하는 것
      • 호출한 메소드로 예외를 전파

예외의 직접 처리

  • try-catch-finally구문

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
      try { 
        
      } catch(ExceotionType1 ex1) {
        
      } catch(ExceotionType2 ex2) {
        
      } finally {
        
      }
    
    • 예외 객체를 throw하는 문장 또는 예외 발생 가능성이 있는 메소드의 호출 부분try블록에 둠
    • 처리하려는 예외 종류에 따라 catch블록을 작성
      • catch블록은 1개의 예외 유형 인자를 가지는 메소드와 유사
      • 여러 예외 유형을 분리해서 처리하려면 catch 블록도 여럿이 됨
    • finally블록은 필요에 따라 작성하며 생략 가능
  • try-catch-finally구문의 실행

    • 실행 중에 예외가 발생하면 try블록은 즉시 종료되고 catch블록이 실행됨
    • catch블록이 여럿이면, catch블록의 매개 변수와 예외 클래스를 비교하여 적합한(발생된 예외 자료형과 일치하거나 상위 유형) 하나만 실행
      • 상위와 하위 유형 예외를 처리하는 catch블록이 모두 있다면, 하위 유형 예외를 처리하는 블록이 먼저 나와야 함
    • try블록에서 예외가 발생하지 않으면 catch블록은 실행 되지 않음
    • finally블록은 예외 발생과 무관하게 항상 실행 됨
      • 할당 받아 사용했던 리소스를 반환하기 위해 즉, 리소스를 close()하는 문장을 finally블록 내에 둠
      • ex) try블록에서 open()했던 파일을 close()하는 코드를 finally블록에 둠

예외 처리 프로그램 예

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Main {
    public static void main(String[] args) {
        try {
            // 예외가 발생할 수 있는 코드 블록
            int[] numbers = { 1, 2, 3 };
            System.out.println(numbers[4]); // 배열 인덱스 범위를 초과하여 예외 발생
            int result = 10 / 0; // ArithmeticException 발생
            System.out.println("결과: " + result);
        } catch (ArrayIndexOutOfBoundsException e) {
            // ArrayIndexOutOfBoundsException 처리
            System.out.println("배열 인덱스가 잘못되었습니다.");
        } catch (ArithmeticException e) {
            // ArithmeticException 처리
            System.out.println("0으로 나눌 수 없습니다.");
        }
        System.out.println("프로그램이 정상 종료됩니다.");
    }
}

// 배열 인덱스가 잘못되었습니다.
// 프로그램이 정상 종료됩니다.

try-with-resources구문

  • 리소스 객체의 선언이 있는 try블록을 가짐

    1
    2
    3
    4
    5
    
      try (리소스 생성 구문) {
        
      } catch (ExceptionType ex) {
        
      }
    
  • 리소스의 유형은 AutoCloseable인터페이스를 구현한 클래스
    • 이때 리소스는 사용 후 close()호출을 통해 반환 되어야 함
    • 파일, 네트워크 연결, 데이터베이스 연결 등 외부 자원을 사용하는 경우 사용함
  • try-with-resource구문을 사용하려면 리소스의 자동 반환을 보장함
    • 즉, finally블록에서 리소스를 close()하지 않아도 됨
  • try-with-resource구문을 사용한 코드

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    
      import java.io.*;
        
      public class Test {
          public static void main(String[] args) {
              try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
                  String line;
                  while ((line = br.readLine()) != null) {
                      System.out.println(line);
                  }
              } catch (IOException e) {
                  e.printStackTrace();
              }
          }
      }
    
  • try-with-resource구문을 사용하지 않은 코드

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    
      BufferedReader br = null;
        
      try {
          br = new BufferedReader(new FileReader("file.txt"));
          String line;
          while ((line = br.readLine()) != null) {
              System.out.println(line);
          }
      } catch (IOException e) {
          e.printStackTrace();
      } finally {
          try {
              if (br != null) br.close();
          } catch (IOException ex) {
              ex.printStackTrace();
          }
      }
    

예외의 간접 처리

  • 예외가 발생할 가능성이 있는 코드를 가진 메소드를 호출하는 쪽에 예외 처리를 위임하는 것
    • 예외의 전파
  • 예외 발생 코드의 예외 처리를 위해 try-catch 블록을 사용하지 않고, 대신 메소드 선언 부에서 발생 시킬 수 있는 예외 유형을 표시함
  • 즉, 메소드 선언에서 괄호 다음에 throws예외 유형을 사용

    1
    2
    3
    4
    5
    6
    7
    
      class CharInput {
          int nInput;
          public char getInput() throws IOException {
              nInput = System.in.read(); //예외 발생 가능
              return (char) nInput;
          }
      }
    
  • 메소드 선언에서 throws절이 표시 된 메소드의 호출은 예외 처리가 필요함

    1
    2
    3
    4
    5
    
      try {
          c = obj.getInput();
      } catch (IOException ex) {
        
      }
    
  • 예외(checked Exception)를 발생 시킬 수 있는 메소드의 예
    • FileInputStream클래스의 생성자

      1
      
        public FileInputStream(String name) throws FileNotFoundException
      
    • InputStream(또는 Reader) 클래스의 메소드

      1
      
        public int read() throws IOException
      
    • 위와 같은 메소드를 호출할 때는 반드시 예외 처리가 필요함

예외 처리 프로그램의 예

  • 예외 처리 프로그램 1

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
      import java.io.*;
        
      public class Main {
          public static void main(String args[]) {
              int b = 0;
              try {
                  b = System.in.read(); // IOException을 발생 시킬 수 있는 메소드기 때문에 예외 처리 필요 
              } catch (IOException ex) {
                  System.out.println(ex);
              }
              System.out.println((char) b);
          }
      }
    
    1
    
      public abstract int read() throws IOException
    
  • 예외 처리 프로그램 2

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    
      import java.io.*;
        
      class CharInput {
          int nInput = 0;
          public char getInput() throws IOException { // 예외 간접 처리로 예외 전파
              nInput = System.in.read();
              return (char)nInput;
          }
      }
        
      public class ExceptionTest4 {
          public static void main(String args[]) {
              CharInput charInput = new CharInput();
              try {
                  System.out.println(charInput.getInput()); // getInput 메소드 호출하여 예외 처리 필요
              } catch (IOException ex) {
                  System.out.println(ex);
              }
          }
      }
    

사용자 정의 예외

  • 사용자가 직접 예외 클래스를 작성할 수 있음
  • 일반적으로 Exception클래스 상속 받음
  • throw구문을 사용하여, 필요할 때 예외 객체를 던질 수 있음

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    
      class MyException extends Exception {
          public MyException() { 
              super(); 
          }
            
          public String toString() { 
              return "MyException";
          }
      }
        
      class MyExceptionTest {
          public void testFunc(int x) throws MyException {
              if (x > 10) 
                  throw new MyException(); // 예외 객체 생성 -> 예외 발생
          }
      }
    



학습 정리


  • Java의 패키지는 관련이 있는 클래스와 인터페이스의 묶음이며 계층 구조로 구성됨
  • 다른 패키지에 있는 클래스를 사용할 때는 import구문을 사용하는 것이 편리함
  • Java 프로그램에서 필요한 클래스나 패키지는 환경 변수 CLASSPATH에 포함되어 있는 경로 상에서 찾을 수 있어야 함
  • Java 프로그램의 실행 도중 심각하지는 않지만 정상적 흐름을 벗어난 비정상적 상황이 발생할 수 있으며 예외라 부름
  • checked Exception에 속하는 예외가 발생할 수 있는 경우, 반드시 예외 처리 구문 작성해야 함
  • 예외의 직접 처리를 위해 try-catch구문을 사용하고, 예외를 전파하려면 메소드 선언에 throws예외 유형을 표시 함



연습 문제


  1. Client 클래스를 myprogram.game패키지에 위치시키려고 한다. Client 클래스를 정의하는 소스 파일의 맨 위에 포함시켜야 코드는 무엇인가?

    a.

    1
    
     package myprogram.game;
    
  2. 밑줄 부분에 들어가야 할 내용은 무엇인가?

    1
    2
    3
    4
    
     public char getInput() /*_____*/ {   
         int nInput = System.in.read(); 
         return (char)nInput;
     }
    

    a.

    1
    
     throws IOException
    
  3. 프로그램 상에 클래스의 완전한 이름인 java.util.Scanner로 표시하지 않고, 단순히 클래스 이름 Scanner만으로 표시하기 위해서 소스 파일의 맨 위에 작성해야 코드는 무엇인가?

    a.

    1
    
     import java.util.Scanner;
    
    1
    
     import java.util.*;
    

[운영 체제] 6강 - 교착 상태

[유비쿼터스 컴퓨팅 개론] 6강 - 유비쿼터스 네트워크