본문 바로가기
Study/JAVA

[JAVA] 11주차_기본 패키지(StringTokenizer 클래스, java.text 패키지, 예외 처리)_자바 스터디

by 8희 2022. 5. 14.

1차시 StringTokenizer 클래스, java.text 패키지

 


StringTokenizer 클래스

- 문자열을 토큰으로 분리하는 데 사용

- 토큰(분리한 문자열)은 공백이나 줄 바꿈 등 구분자를 사용해 문자열을 분리

- 기본 구분자는 공백, 탭, 줄 바꿈, 복귀, 용지 먹임 문자

 

StringTokenizer 클래스의 주요 생성자

 

StringTokenizer 클래스가 제공하는 주요 메서드

 

/* StringTokenizer 클래스의 활용 */

import java.util.StringTokenizer; //StringTokenizer 사용을 위해서는 import 선언 필수!

public class StringTokenizerDemo {
	public static void main(String[] args) {
		String s = "of the people, by the people, for the people"; //String 객체 생성

		//" ," 공백과 콤마를 구분자로 파싱한 StringTokenizer 객체 생성
		StringTokenizer st = new StringTokenizer(s, " ,");
        
        	//StringTokenizer st = new StringTokenizer(s); 
        	//이렇게 하는 경우 기본 구분자인 공백으로 파싱!
		
        	//남아 있는 토큰의 개수 반환 메서드
		System.out.println(st.countTokens()); //(1)토큰의 개수 출력 

		//토큰이 남아 있을 때까지 다음 토큰을 꺼내어 출력
		while (st.hasMoreTokens()) { //남아 있는 토큰이 있는지 여부 반환 메서드
			System.out.print("[" + st.nextToken() + "] "); //(2)다음 토큰을 꺼내 오는 메서드
		}
	}
}

//코드 실행 결과 (1), (2)
//9
//[of] [the] [people] [by] [the] [people] [for] [the] [people]

 

 


Random 클래스

- 난수 반환

- 동일한 시드를 사용해 생성된 Random 객체는 동일한 난수 발생

 

Random 객체를 생성하는 Random 클래스의 주요 생성자

 

Random 클래스가 제공하는 주요 메서드

 

/* Random 클래스의 활용 */

import java.util.Random; //import java.util.*로 선언도 가능

public class RandomDemo {
	public static void main(String[] args) {
		Random r = new Random(); //랜덤 객체 생성

		for (int i = 0; i < 5; i++) //난수 5번 발생
			System.out.print(r.nextInt(100) + " "); //0 ~ 100 사이의 int 타입 난수 발생시킴
            	//대체적으로 랜덤은 0부터 시작, 따라서 이렇게 난수를 발생시키면 0 ~ 99까지의 난수만 발생
            
            	//Systme.out.print(r.nextInt(100)+1 + " ");
            	//이렇게 산술 연산해서 범위 지정해야 100도 난수로 발생시킬 수 있음!
	}
}

 


java.text 패키지

- 현지화가 필요한 데이터의 효율적 처리를 위한 패키지

- 시스템을 현지에 맞게 데이터를 가져가는 것! (데이터가 변하는 것은 아님)

- 패키지의 Format 클래스는 지역에 민감한 데이터를 현장에 맞게 문자열로 표현하고 포맷할 수 있도록 지원

 

Format 클래스의 계층 구조 (우리는 MessageFormat과 DecimalFormat을 다룸)

 


MessageFormat 클래스

- 문자열을 특정 포맷에 맞추어 깔끔하게 처리하는 클래스

/* MessageFormat 클래스 사용 방법 */

//(1) {0}, {1}, {2}가 인덱스!
MessageFormat.format("{0} * {1} = {2}", 3, 4, 3 * 4);

//(2) 객체 배열을 만들어서 배열의 인덱스를 그대로 매핑하는 방법
MessageForamt.format("{0} * {1} = {2}", new Object[]{3, 4, 3 * 4});

//대체적으로 (2)를 더 많이 사용

 

import java.text.MessageFormat; //MeessageFormat은 java.text 패키지 소속!

public class MessageFormatDemo {
	public static void main(String[] args) {
		String java = "Java";
		int version = 8;
        
        	//패턴 메시지 version: 패턴 메세지의 {0}에 대응
        	//패턴 메시지 java: 패턴 메세지의 {1}에 대응
        	//인덱스인 {1}과 {0}은 포맷이므로 순서를 바꿀 수 있지만
        	//version과 java는 정확하게 순서대로 카운트 됨!
        	//그래서 {0}에 version, {1}에 java
		String s = MessageFormat.format("language : {1}\nversion : {0}", version, java);
        	//\n은 줄 바꾸기

		System.out.println(s);
        
        	//배열로 접근 - 객체 배열을 만들어서 배열의 인덱스를 그대로 매핑
		Object[] data = { java, version }; //업캐스팅 발생
        	//Object는 객체에 대한 최상위 클래스
        	//java라는 String 객체가 배열에 들어와서 <부모 자식>의 형태가 되므로 업캐스팅 발생!

		MessageFormat f = new MessageFormat("language : {0}\nversion : {1}");
        	//{0}에 java, {1}에 version 매핑

		System.out.println(f.format(data));
        	//MessageFormat.format(배열)의 형태
	}
}

 

 


DecimalFormat 클래스

- 10진수를 포맷. 정수, 실수, 과학적 표기, 퍼센트 표시, 화폐 표시 등을 포함한 다양한 종류의 수를 지원

- #이랑 0으로 판단해서 범위 지정

DecimalFormat 클래스에서 사용할 수 있는 패턴 기호

 

DecimalFormat 클래스 사용 방법

 

/* DecimalFormat 클래스의 활용 */

import java.text.DecimalFormat; //DecimalFormat 클래스는 java.text 패키지 소속!

public class DecimalFormatDemo {
	public static void main(String[] args) {
		DecimalFormat f1 = new DecimalFormat("#");
		DecimalFormat f2 = new DecimalFormat("000000000.00");
		DecimalFormat f3 = new DecimalFormat("#.000");
		DecimalFormat f4 = new DecimalFormat("#,###.##");
		DecimalFormat f5 = new DecimalFormat("-#.#");
		DecimalFormat f6 = new DecimalFormat("#.##E00");
		DecimalFormat f7 = new DecimalFormat("+#.#;-#.#");
		DecimalFormat f8 = new DecimalFormat("#.00%");

		//입력 숫자: 1234567.890
		System.out.println(f1.format(1234567.890));
		System.out.println(f2.format(1234567.890));
		System.out.println(f3.format(1234567.890));
		System.out.println(f4.format(1234567.890));
		System.out.println(f5.format(1234567.890));
		System.out.println(f6.format(1234567.890));
		System.out.println(f7.format(1234567.890));
		System.out.println(f7.format(-1234567.890));
		System.out.println(f8.format(1234567.890));
	}
}

 


2차시, 3차시 예외 처리

 


예외의 개념

- 에러(error): 개발자가 해결할 수 없는 치명적인 오류

- 예외(exeption): 개발자가 해결할 수 있는 오류

- 예외가 발생하면 비정상적인 종료를 막고, 프로그램을 계속 진행할 수 있도록 우회 경로를 제공하는 것이 바람직

- 예외를 그대로 보여주는 게 아니라 우회해서 보여준다는 뜻!

- 예외 처리는 자바에만 있는 기능 ~ (자바는 예외를 객체로 처리)

- 오류(error)에 오류(error)와 예외(exception)이 포함됨

 

예외의 종류

- 일반 예외만 컴파일러가 확인 (코드에서 빨간 색 밑줄 뜨는 거)

- 실행 예외는 코드에서 처리하든지 JVM에 맡기든지 개발자가 선택

 

실행 예외

- 예외가 발생하면 JVM은 해당하는 실행 예외 객체 생성

- 실행 예외는 컴파일러가 예외 처리 여부를 확인 X, 따라서 개발자가 예외 처리 코드의 추가 여부 결정

 

대표적인 실행 예외

 

/* 실행 예외 1 */

import java.util.NoSuchElementException; //import java.util.*; 가능
import java.util.StringTokenizer; //StringTokenizer 클래스

public class UnChecked1Demo {
	public static void main(String[] args) {
		String s = "Time is money";
		StringTokenizer st = new StringTokenizer(s); //구분자가 없으므로 기본 구분자인 공백으로 파싱 
		
        	//토큰이 남아 있을 때까지 다음 토큰을 꺼내어 출력
		while (st.hasMoreTokens()) { 
			System.out.print(st.nextToken() + "+");
		}
        	//예외 발생 시점 
		System.out.print(st.nextToken()); //더 이상 가져올 토큰이 없어 예외를 발생시킴
        	//이미 while문 안에서 토큰 다 출력했음
}

NoSuchElementException - 요구한 원소가 없을 때 발생

 

/* 실행 예외 2 */

//java.lang 패키지 에러는 import 생략 가능

public class UnChecked2Demo {
	public static void main(String[] args) {
		int[] array = { 0, 1, 2 };

		//예외 발생 시점
		System.out.println(array[3]); //범위를 벗어난 인덱스를 사용해 예외 발생 시킴
	}
}

ArrayIndexOutOfBoundsException - 범위를 벗어난 인덱스를 사용할 때 예외 발생

 

일반 예외

- 소스 코드에서 빨간 색 밑줄이 보이는 경우

- 컴파일러는 일반 예외가 발생할 가능성을 발견하면 컴파일 오류를 발생

- 개발자는 예외 처리 코드를 반드시 추가

 

대표적인 일반 예외 예

 

/* 일반 예외 */

public class CheckedDemo {
	public static void main(String[] args) {
		Thread.sleep(100);
        	//일반 예외가 발생할 수 있는 코드.
        	//예외 처리를 하지 않아 컴파일 오류 발생
	}
}

 


예외 처리 방법

1. 예외 잡아 처리하기 (try~catch~finally 문)

2. 예외 떠넘기기 (throws문)

 

예외 잡아 처리하기 

- 예외가 발생한 시점에 예외 객체를 잡아 바로 처리할 때는 try~catch문 사용

- 예외 발생 여부와 관계 없이 반드시 수행할 실행문이 있다면 try~catch 코드에 finally 블록 추가

- 예외와 관련된 정보는 Throwable 클래스에 있는 메서드에서 얻을 수 있다.

- 핸들러의 부모가 Throwable 객체

 

try~catch문

 

예외가 발생할 때 try~catch 유무에 따른 결과

 

Throwable 클래스의 주요 메서드

 

/* try~catch문을 사용해 예외 잡아 처리하기 */
/* (1) ~ (4) 순서대로 실행 */

//java.lang 패키지에 포함되는 예외라 import 생략 가능

public class TryCatch1Demo {
	public static void main(String[] args) {
		int[] array = { 0, 1, 2 }; //(1)
		try {
        		//array는 3개의 원소만 있으므로 array[3]은 없음! 예외 발생!
			System.out.println("마지막 원소 => " + array[3]); //(2) 예외 발생해서 출력 X
            		//이전 실행문에서 예외가 발생했으므로 다음 실행문은 실행 X
			System.out.println("첫 번째 원소 => " + array[0]);
		} catch (ArrayIndexOutOfBoundsException e) {
			System.out.println("원소가 존재하지 않습니다."); //(3)
		}
        	//꼭 실행해야 하는 문장은 try문 밖에 위치!
		System.out.println("어이쿠!!!"); //(4)
	}
}

//실행 결과
//원소가 존재하지 않습니다.
//어이쿠!!!

 

/* 인수를 받아 나눗셈을 수행하는 과정에서 발생하는 예외 잡아 처리하기 */

public class TryCatch2Demo {
	public static void main(String[] args) {
		int dividend = 10;
		try {
			int divisor = Integer.parseInt(args[0]);
			System.out.println(dividend / divisor);
            
        	//ArratIndexOutOfBoundsException은 배열의 범위를 벗어난 인덱스 사용 시 발생
        	//여기서는 main()의 인수가 없을 때 발생
		} catch (ArrayIndexOutOfBoundsException e) {
			System.out.println("원소가 존재하지 않습니다.");
            
        	//NumberFormatException은 main()의 인수를 숫자로 바꿀 수 없을 때 발생
		} catch (NumberFormatException e) {
			System.out.println("숫자가 아닙니다.");
            
        	//ArithmeticException은 main()의 인수가 9일 때 나눌 수 없으므로 발생
		} catch (ArithmeticException e) {
			System.out.println("0으로 나눌 수 없습니다.");
            
        	//finally는 예외 발생과 관계 없이 항상 실행 (finally 블록은 선택 사양)
        	//finally 블록 사용 시 코드의 가독성 증가
		} finally {
			System.out.println("항상 실행됩니다.");
		}
		System.out.println("종료.");
	}
}

 

/* 예외 잡아 처리하기 - 컴파일 오류 발생 코드 */

public class TryCatch3Demo {
	public static void main(String[] args) {
		int[] array = { 0, 1, 2 };
		try {
			int x = array[3];
        
        	//Exception 객체를 처리하는 catch 블록에서 모든 예외를 처리하므로 
        	//ArrayIndexOutOfBoundsException 객체를 처리하는 catch 블록은 도달할 수 없음
        	//따라서 컴파일 오류 발생
        	//Exception 객체가 최상위(부모)라서 나중의 다른 것들은 의미가 없음!
            	//부모는 맨 마지막에 위치해야 오류 발생 X!
		} catch (Exception e) {
			System.out.println("어이쿠!!!");
		} catch (ArrayIndexOutOfBoundsException e) {
			System.out.println("원소가 존재하지 않습니다.");
		}
		System.out.println("종료.");
	}
}

 

예외 떠넘기기

- 메서드에서 발생한 예외를 내부에서 처리하기가 부담스러울 때는 throws 키워드를 사용해

  예외를 상위 코드 블록으로 양도 가능

- 현재 메서드에서 예외를 처리하지 않고 현재 메서드를 호출한 곳으로

  발생한 예외 객체를 대신 처리해 달라고 떠넘기는 것!

/* 예외 떠넘기기 사용 방법 */

public void write(String filename)
	throws IOEception, ReflectiveOperationException { //예외 1개 이상 선언 가능
    	//파일 쓰기와 관련된 실행문...
    } //throws는 예외를 다른 메서드로 떠넘기는 키워드!
    
    //자바 API 문서를 보면, 많은 메서드가 예외를 발생시키고 상위 코드로 예외 처리를 떠넘김.

 

/* 호출된 메서드가 호출한 메인 메서드에 예외 떠넘기기 */

import java.util.Scanner;

public class ThrowsDemo {
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		try {
        	//square()에서 예외 발생 시 스스로 처리하지 않고 여기서 처리
			square(in.nextLine());
		} catch (NumberFormatException e) {
			System.out.println("정수가 아닙니다.");
		}
	}
	
    //호출한 메서드에서 예외를 처리하도록 떠넘기기
	private static void square(String s) throws NumberFormatException {
    	//s가 문자열이 아니면 NumberFormatException 예외 발생
		int n = Integer.parseInt(s);
		System.out.println(n * n);
	}
}