학습 개요
- 패키지는 관련이 있는 클래스나 인터페이스의 묶음으로, 계층 구조로 이루어진 클래스나 인터페이스의 라이브러리임
- 예외는 실행 중에 발생하는 경미한 오류이며, 예외 처리를 통해 정상 상황으로 복구 될 수 있음
- 패키지를 정의하고 사용하는 방법과 예외 처리 개념을 이해하고 활용할 수 방법을 익히도록 함
학습 목표
- 사용자 패키지 정의할 수 있음
- 정의된 패키지를 사용하여 프로그램 작성할 수 있음
- 예외의 종류 설명할 수 있음
- 예외 처리 코드 작성할 수 있음
강의록
패키지
패키지
- 관련이 있는 클래스와 인터페이스의 묶음
- 클래스와 인터페이스는 패키지의 멤버로 존재
- 패키지는 클래스와 인터페이스의 .class 파일이 저장된 폴더
- 전체적으로 패키지는 계층 구조로 이루어짐
- 패키지(폴더와 유사) 단위로 계층 적으로 분류됨
- 패키지의 용도
- 클래스를 쉽게 찾아 사용하기 위해
클래스의 이름 충돌을 피하기 위해
1
import graphics.Rectangle
1
import java.awt.Rectangle
- 클래스의 접근 범위를 제어하기 위해
시스템 패키지
- JDK가 제공하는 클래스 라이브러리
- JDK와 함께 설치됨
- 클래스 파일들은 기능에 따라 패키지로 묶여 분류됨
- 과거에는 jar 파일로 압축되어 있었음
ex)
1
rt.jar
- 최근 버전에는 모듈 단위로 분산 되어 저장되어 있음
- 과거에는 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
과 같이 완전한 이름으로 표현하는 것이 원칙임
- ex)
사용자 정의 패키지
패키지 정의
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
- 컴파일 할 때 -d 옵션 사용하여 지정함
Eclipse에서 사용자 패키지 정의하기
- 메뉴 File → New → Package 선택
- 패키지에 해당하는 폴더가 만들어짐
- 생성된 패키지에서 클래스를 만들면 됨
또는 메뉴 File → New → Class 선택하여 클래스 이름과 함께 패키지 이름을 함께 입력함
패키지와 클래스의 사용
- 다른 패키지에 존재하는
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()
메소드 등을 상속 받음
- Unchecked Exception
- 예외 처리 코드 강제성 없음
- Checked Exception
- 반드시 예외 처리 코드 필요
예외 처리
- 예외가 발생했을 때 이 상황을 바로 잡아 계속 수행하도록 하는 것
예외 발생 시, Exception 객체를 생성하고 throw함
1
throw new MyException();
- throw 된 예외 객체를 예외 처리 코드가 catch하여 예외를 처리함
- 예외 발생과 처리
- checked Exception 예외가 발생할 수 있는 경우, 반드시 명시적인 예외 처리가 필요함
- 예외 처리 코드가 없으면 컴파일 오류
RuntimeException
예외의 경우, 예외 처리를 안 해도 됨- 프로그램을 정확하게 작성하지 않은 경우 발생 됨
ArithmeticException
,NullpointerException
,IndexOutOfBoundsException
등
- checked Exception 예외가 발생할 수 있는 경우, 반드시 명시적인 예외 처리가 필요함
예외 처리 방법
- 직접 처리
- 예외가 발생한 곳에서 예외 객체를 잡아서 처리하는 것
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
블록은 필요에 따라 작성하며 생략 가능
- 예외 객체를 throw하는 문장 또는 예외 발생 가능성이 있는 메소드의 호출 부분을
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
예외 유형을 표시 함
연습 문제
Client 클래스를
myprogram.game
패키지에 위치시키려고 한다. Client 클래스를 정의하는 소스 파일의 맨 위에 포함시켜야 코드는 무엇인가?a.
1
package myprogram.game;
밑줄 부분에 들어가야 할 내용은 무엇인가?
1 2 3 4
public char getInput() /*_____*/ { int nInput = System.in.read(); return (char)nInput; }
a.
1
throws IOException
프로그램 상에 클래스의 완전한 이름인
java.util.Scanner
로 표시하지 않고, 단순히 클래스 이름Scanner
만으로 표시하기 위해서 소스 파일의 맨 위에 작성해야 코드는 무엇인가?a.
1
import java.util.Scanner;
1
import java.util.*;