람다식(Lambda) 

- JDK 1.8에서 추가된 문법

- FunctionallInterface를 편하게 사용할 수 있는 문법

   > FunctionallInterface : abstract method를 하나만 가진 인터페이스

- interface를 구현한 클래스를 작성하거나, anonymous inner class를 만들지 않고 사용할 수 있는 방법

- 문법)   인터페이스명 객체명 = (매개변수,,,) -> { 코드 } ;

 

* interface위에 @FunctionallInterface라는 annotaion을 설정하면

  해당 인터페이스는 추상 method를 반드시 하나만 가져야 함!

 


# 오늘의 코딩 #

- 람다식을 알아보쟈!

 

1) 매개변수가 없는 인터페이스

@FunctionalInterface  // 추상method를 반드시 하나만 가지는 interface가 작성되어야 함
public interface TestLambda {

	public void method();
//	public void method1(); //error!@FunctionalInterface 가 들어가면 추상메소드가 하나여야함
	
}

2) 매개변수가 있는 인터페이스

@FunctionalInterface  // 추상method를 반드시 하나만 가지는 interface가 작성되어야 함
public interface TestLambda2 {
	//매개변수가 있는 abstract method
	public void method(int i, String str);
	
}

3) 매개변수와 반환형이 있는 인터페이스

@FunctionalInterface  // 추상method를 반드시 하나만 가지는 interface가 작성되어야 함
public interface TestLambda3 {
	//매개변수와 반환형이 있는 abstract method
	public String luckNum(String name);
	
}

4) 1,2,3 인터페이스를 사용할 class!

import java.util.Random;

/**
 * 람다식의 사용
 */
public class UseLambda {

	public static void main(String[] args) {
		/////////// 매개변수가 없는 abstarct method////////////////
		// 1. 매개변수가 없는 abstract method
		TestLambda tl = () -> {
			System.out.println("추상 method를 구현");
		};
		// 2. 호출
		tl.method();

		/////////// 매개변수가 있는 abstarct method////////////////
		// 1. 매개변수가 있는 abstract method
		TestLambda2 tl2 = (int i, String msg) -> {
			System.out.println("매개변수있는 추상 method를 구현");
			System.out.println("i=" + i + ",msg=" + msg);
		};
		// 2.호출
		tl2.method(2021, "오늘은 날이 좋네요!");

		/////////// 반환형이 있는 abstarct method////////////////
		TestLambda3 tl3 = (String name) -> {
			Random random = new Random();
			int num = random.nextInt(101);
			return name + "님의 행운의 번호 : " + num;
		};

		//호출
		String msg = tl3.luckNum("동동"); 
		System.out.println(msg);
	}// main

}// class

 

# 출력 결과 #

 

-- functionallInterface의 경우에는 lambda식이 정말 편한 방법인 것 같다 

 1. charset 

- 컴퓨터에서 문자를 사용하기 위해 미리 정의해둔 문자 테이블

- 종류 : 완성형 charset, 조합형 charset  // 조합형 charset은 지금 없어짐

- 조합형 : 자음과 모음을 조합하여 글자를 생성, 모든 한글을 표현할 수 있음 (예전 아래아한글이 제공)

- 완성형 : 모든 글자를 만들어 두고 사용하는 charset, charset에 존재하지 않는 문자는 표기할 수 없음

   

*  1byte charset, 2byte charset, 3byte charset이 있음

  • 1byte charset : 8859_1 => 영어(대,소), 숫자, 특문
  • 2byte charset : EUC-KR(국제표준), KSC5601(국내표준-X), MS949(마이크로소프트사-기업) => 영어(대,소), 숫자, 특문, 한글
  • 3byte charset : UTF-8(국제표준) => 영어(대,소), 숫자, 특문, 한글 => 국제 표준인 UTF-8을 많이 씀

 

 2. early return 

- method의 반환형이 void인 경우 값을 가지지 않은 return을 사용할 수 있음

- 괄호 갯수가 줄어서 가독성이 향상됨

- Ex. if~else문의 경우, if가 엄청나게 길때 사용하면 좋음!!

  기존 구문의 경우)

            return 값;

           -> 반환형이 존재할 때 사용하는 return, 값을 내보내는 일

  early return의 경우)

            return ;

           ->  반환형이 존재하지 않을 때 사용하는 return - 아랫줄의 코드를 실행하지 않고 호출한 곳으로 돌아가는 일

~전편에 이어서~

ObjectStream을 활용해보자!

 


# 오늘의 코딩 #

[순서]

1. 먼저 내보낼 객체의 기반이 되는 'MyData' Class를 생성 (Serializable interface를 구현한 클래스) 

2. ObjectStream활용을 위한 클래스를 생성하여 write와 read method를 작성/실행해보자

 

#1. MyData Class

- 사용자 정보를 가지고 있으며 직렬화가 막혀있는 변수가 존재함

package test;

import java.io.Serializable;

/**
 * 사용자의 정보를 가진 클래스
 * @author user
 */
public class MyData implements Serializable{
		
	/**
	 * serialVersionUID : 이 클래스 파일이 JVM 외부로 빠져나갔을 때 파일을 검증하기 위한 용도의 Constant
	 * 객체가 JVM 외부로 나갔을 때 검증하기 위해서 ID를 부여함
	 * 1. 현재 JVM에서 빠져나간 객체임을 검증 가능
	 * 2. 시간에 대한 체크 가능
	 */
	private static final long serialVersionUID = -6444648902030740467L;
	private double height;
	private transient double weight; // 직렬화를 막기 위해서는 transient를 걸자 (직렬화 방지)
	private int age;
	private transient String name; // 직렬화 방지
	
	public MyData() {
	}

	public MyData(double height, double weight, int age, String name) {
		this.height = height;
		this.weight = weight;
		this.age = age;
		this.name = name;
	}

	public double getHeight() {
		return height;
	}

	public void setHeight(double height) {
		this.height = height;
	}

	public double getWeight() {
		return weight;
	}

	public void setWeight(double weight) {
		this.weight = weight;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Override
	public String toString() {
		return "MyData [height=" + height + ", weight=" + weight + ", age=" + age + ", name=" + name + "]";
	}
	
}//class

 

#2. UseObjectStream Class

1) MyData Class를 활용하여 객체 내보내기/읽기 Stream을 실행하는 class

package test;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.NotSerializableException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

/**
 * 객체를 직렬화하여 JVM외부로 내보내거나 읽어들이는 클래스
 */
public class UseObjectStream {

	public void writeObj(MyData md) throws IOException, NotSerializableException {
		// 1. 스트림 생성
		ObjectOutputStream oos = null;
		try {
			oos = new ObjectOutputStream(new FileOutputStream(new File("C:/Users/user/Desktop/obj.txt")));
			// 2. 객체 스트림에 기록
			oos.writeObject(md);
			// 3. 스트림의 내용 분출
			oos.flush();
		} finally {
			// 4. 연결 끊기
			if (oos != null) {
				oos.close();
			}//end if
		}//end finally
	}// writeObj

	public MyData readObj() throws IOException, ClassNotFoundException {
		MyData md = null;

		// 1. 스트림 생성
		ObjectInputStream ois = null;
		try {
			ois = new ObjectInputStream(new FileInputStream(new File("C:/Users/user/Desktop/obj.txt")));
			// 2. 스트림에서 객체 읽기
			md = (MyData) ois.readObject(); // method 반환형이 object이므로 클래스로 casting 해줘야 값을 받아올 수 있음
		} finally {
			// 3. 연결 끊기
			if (ois != null) {
				ois.close();
			} // end if
		} // end fianlly
		return md;
	}// readObj

 

2) main maethod에서 실행해보자!! writeObj를 먼저 실행하면!

	public static void main(String[] args) {

		MyData md = new MyData(180.3, 73.2, 26, "김동동");
		UseObjectStream uos = new UseObjectStream();

		try {
			uos.writeObj(md);
			System.out.println("직렬화된 객체:" + md);
		} catch (NotSerializableException nse) {
			System.out.println("객체가 직렬화되지 않습니다.");
			nse.printStackTrace();
		} catch (IOException ie) {
			System.out.println("객체를 쓰는 동안 문제 발생");
			ie.printStackTrace();
		} // end catch

	}// main

}// class

# 출력 결과 #

- JVM외부로 나간 객체의 내용 & 설정한 경로에 작성된 파일

 

 

3) readObj method도 실행해보자!

		try {
			MyData md1 = uos.readObj();
			System.out.println("역직렬화된 객체:" + md1);
		} catch (ClassNotFoundException cnfe) {
			cnfe.printStackTrace();
		} catch (IOException ie) {
			ie.printStackTrace();
		} // end catch
		
	}// main

}// class

 

# 출력 결과 #

- MyData Class에서 직렬화 방지를 위해 transient로 막아둔 변수는 null로 읽힘 

  >> 해당 변수는 JVM외부로 나가지 않았다라는 것 확인!

 

 1. 직렬화 (Serializable) 

객체를 일정 크기로 쪼개는 것.

- 단, 모든 객체는 직렬화되지 않음 (직렬화 되어져야 하는 객체는 java.io.Serivalizable 인터페이스를 구현한 클래스만 가능)

- Serializable 인터페이스를 구현한 클래스로부터 생성된 instance는 일정 크기로 쪼개질 수 있음

 

* Serializable 인터페이스는 Constant와 abstract method가 없음

   - 목적 : 데이터형에 체크 (is a 관계에 대한 확인용)

   - interface에 상수/추상메소드가 없고 -able로 명명되어있으면 특정한 용도를 확인하기 위한 interface인 경우가 많다!

 

 2. transient 

- 직렬화를 막는 키워드로 변수의 접근지정자 종류

  > 객체가 가진 중요한 정보를 JVM안에서만 사용하도록 만들 수 있음 (JVM밖으로 못 나감)

- 문법)

public class Test implements Serializable{

           int i; // 직렬화 가능

           String str; // 직렬화 가능 (String이 serializable을 implements함)

           transient String str1; // serializable보다 transient가 우선되어 직렬화 막기 가능

           private transient int j; // 직렬화 막기 }

 

 3. ObectStream 

- JVM에 생성된 instance(객체)를 JVM 외부로 내보내거나,

  JVM외부에 존재하는 객체를 JVM내부로 읽어 들일 때 사용하는 Stream

- 기본형 데이터형은 JVM외부로 나갈 수 있으나 instance는 JVM외부로 나갈 수 없음

  > 기본형 데이터형은 크기가 정해져 있어서 쪼갤 수 있음

  > 인스턴스는 클래스가 Serializable 인터페이스를 구현해야 직렬화 가능

- ObjectInputStream, ObjectOutputStream 사용 (8bit Stream)

 

 4. serialVersionUID 

- 이 클래스 파일이 JVM 외부로 빠져나갔을 때 파일을 검증하기 위한 용도의 Constant

- 용도 1) 현재 JVM에서 빠져나간 객체임을 검증 가능

  용도 2) 시간에 대한 체크 가능 (만약 내가 1년뒤에 ID 번호를 바꾸면 읽어들일 때 오류 발생!!)

- 클래스는 직렬화되어서 JVM밖으로 나갔다가 조작될 수 있는 위험(보안상의 위험)이 있기 때문에

  JVM이 serial warinng을 띄움

  > 이를 검증하기 위해 serialVersionUID를 거는 것이다!

- @SuppressWarnings(“serial”) 어노테이션 처리를 해도 되지만 ID부여가 안전함

 

- EX)

private static final long serialVersionUID = -8401830166169521484L; // 내보냈을 때 기존 ID

private static final long serialVersionUID = -8401830166169521485L; // 바뀐 ID

 

이후 .readObject();를 시행하면 아래와 같은 [InvalidClassException]이 발생함!

 

// 콘솔창 오류 내용 :
java.io.InvalidClassException: day0818.MyData; local class incompatible: stream classdesc serialVersionUID = -8401830166169521484, local class serialVersionUID = -8401830166169521485

(ID가 바뀌어서 유효한 클래스가 아니라는 의미! -> 밖에 있는 직렬화된 클래스가 내부로 들어오지 못함)

 

 

 

코딩은 다음편에!

~전편에 이어서 2~

오늘은 Stream으로 파일 쓰기!

 

 1. 8bit Stream 활용 

- 전 편에서 사용했던 java_test.txt 파일을 읽어서 새로운 파일을 써보자

- test라는 글자가 적혀있음

- FileInputStream과 FileOutputStream을 사용하면 됨

- 파일 복사도 1byte씩 읽어들인 것을 다른 파일에 flush하면서 진행됨 

  >> byte의 array를 만들어서 1byte가 아니라 더 많은 byte를 읽어들이면 파일 복사 효율 증대

 

# 코딩 #

- 이전에 만들었던 클래스에서 이어서 method 작성!

	/**
	 * 8bit Stream 사용하여 text 파일 쓰기
	 * 
	 * @throws IOException
	 */
	public void usestream3() throws IOException {
		File inFile = new File("C:/Users/user/Desktop/java_test.txt"); // 읽어올 파일
		File outFile = new File("C:/Users/user/Desktop/java_output_test.txt"); // 작성할 파일

		FileInputStream fis = new FileInputStream(inFile); // 파일에 스트림 연결
		FileOutputStream fos = new FileOutputStream(outFile); // 파일에 스트림 연결

		int val = 0;
		while ((val = fis.read()) != -1) { // 읽어들일 데이터가 없을 때까지 while 실행
			fos.write(val); 읽어들인 데이터를 val에 넣고 새 파일에 write
		}
		fis.close(); // 스트림 닫자!
		fos.close();

	}// usestream3

 

# 출력 결과 #

새로운 파일이 복사되었고 test 문장이 잘 나왔다!

복사된 파일
출력 결과창

 


 

2. 16bit Stream 활용

- 이번에는 한글을 작성해보자

- 한글은 16bit Stream 이용해야함!

- Java에서 기본형 데이터형의 경우에는 flush()를 하지 않더라도 Stream에 있는 데이터가 HDD로 나가지만, 

  다른 데이터의 경우에는 꼭 flush()를 해주어야 함!!

 

# 코딩 #

	/**
	 * 16bit Stream 사용하여 text 파일 쓰기
	 * 
	 * @throws IOException
	 */
	public void usestream4() throws IOException {
		File file = new File("C:/Users/user/Desktop/java_output_test2.txt"); // 생성할 파일

		BufferedWriter bw = new BufferedWriter(new FileWriter(file));

		bw.write("안녕하세요");
		bw.flush(); // 데이터 내보내기
		bw.close(); // 스트림 닫자

	}// usestream4

# 출력 결과 #

한글도 데이터 내보내기 완료!

새로 생긴 파일
출력 결과창

 

~전편에 이어서~

오늘은 Stream을 활용하여 파일을 읽어보자!

 

1. 8bit Stream 활용

영어, 숫자는 1byte이므로 읽혀 지지만, 한글은 2byte 이므로 읽혀 지지 않음

- 방법)

① File에 연결할 수 있는 Stream을 생성

    FileInputStream fis = new FileInputStream(new File(“파일경로”)); //FileNotFoundException 

② 스트림에서 내용 읽기 

     > 스트림에 연결된 파일의 내용을 1byte씩 읽어 들임

     > 읽어들인 데이터가 존재하지 않으면 -1이 나옴.

     > IOException 처리 필요

           int value = 0;

           while ( (value = fis.read()) != -1 ) { // 파일 내용의 크기가 얼마나 될지 모르니 while사용

                    value 사용 }; 

 

# 코딩 # 

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;

public class UseStream {

	/**
	 * 8bit Stream 사용하여 text 파일 읽기
	 * @throws IOException
	 */
	public void usestream1() throws IOException {
		FileInputStream fis = new FileInputStream(new File("C:/Users/user/Desktop/tistory/java_test.txt")); // 파일에 스트림 연결
		
		int val = 0; // 스트림에 연결된 파일의 내용을 1byte씩 읽어 들이며 반환형이 int
		
		while ((val = fis.read()) != -1) { // 읽어들인 데이터가 존재하지 않으면 -1이 나옴 -> 데이터가 있을 때까지 읽어들임
			System.out.print((char) val);
		} // end while

		fis.close(); // stream 닫기!

	}// usestream1

- UseStream이라는 Class를 생성한 후 8bit Stream을 사용할 method를 작성했다!

- main method에서 클래스 객체 생성 후 method를 실행하면 아래와 같이 결과가 나온다.

- throws한 IOException은 method수행 시 try~catch로 처리했고,

  경로에 있는 java_test.txt는 'test'라는 영문 글자를 가지고 있당

 

# 출력 결과 #

test


 

2. 16bit Stream 활용

- 16bit Stream은 문자열을 입력받기 위해 고안된 Stream으로

  FileReader(HDD 파일과 연결) BufferedReader(스트림에서 연결된 파일에서 줄 단위로 읽음)를 사용하면 편함

  >> 연결된 파일을 줄 단위로 읽을 수 있음 (readLine())

- 방법)

① File에 연결할 수 있는 Stream을 생성

    FileReader fr = new FileReader(new File(“파일경로”));

② 부족한 기능을 제공하는 스트림 연결 (줄 단위로 읽어들이는 기능)

           BufferedReader br = new BufferedReader( fr );

③ 스트림에서 내용 읽기

       > 스트림에 연결된 파일의 내용을 줄 단위로 읽어 들임

       > 읽어들인 데이터가 존재하지 않으면 null이 나옴.

           String value = “”;

           while ( (value = br.readLine()) != null ) { // 줄 단위로 읽어서 저장하고 읽어들인 줄이 없으면 null이 반환됨

                    value 사용 } ;

 

# 코딩 # 

	/**
	 * 16bit Stream 사용하여 text 파일 읽기
	 * 한글은 16bit Stream으로 해야 깨지지 않음
	 * @throws IOException
	 */
	public void usestream2() throws IOException {
		FileReader fr = new FileReader(new File("C:/Users/user/Desktop/tistory/java_test1.txt"));
		BufferedReader br = new BufferedReader(fr); // BufferedReadr로 line을 읽어들이자. 속도향상! 

		String val = ""; // readLine method의 반환형은 String

		while ((val = br.readLine()) != null) { // 읽어들일 데이터가 없다면 null이 나옴
			System.out.print(val);
		} // end while
		
		br.close(); // 스트림 닫자!
	}// usestream2

- 이번 경로에 있는 java_test1의 내용은 한글이며 출력이 잘 읽히는 것을 확인할 수 있다!

 

# 출력 결과 #

안녕하십니까!반갑습니다.

 

 

 

 

 1. IO(Input/Output) Stream 

- JVM에서 JVM외부에 존재하는 데이터를 읽어들이거나(Input),

  JVM내부의 데이터를 JVM외부로 내보낼 때(Output) 사용하는 기술 (txt, dat만 가능)

- 독자 포맷(hwp,xls,ppt)이 있는 파일은 읽어 들일 수 있지만 내용을 확인할 수 없음

- 독자 포맷의 파일을 생성할 수 없음

- java.io.package에서 관련 클래스를 제공

- 8bit stream(byte 기반)과 16bit stram(문자열 기반)이 제공

- 단방향 스트림 (읽기 스트림은 읽기만 가능하고, 쓰기 스트림은 쓰기만 가능)

- 스트림은 연결해서 사용할 수 있음 (FileReader랑 BufferedReader 같이 사용하는 등)

- Stream은 사용 후 꼭 close()! // 스트림을 끊어서 메모리 누수(memory leak)을 막자

 

 1) 8bit Stream 

- byte 기반 스트림

- 모든 data를 읽고 쓸 수 있는 스트림

- 한 byte씩만 읽어들일 수 있음

- 파일 복사에 많이 씀

- 16bit Stream보다 속도가 빠름 / 단, 한 번에 보내고 받는 양은 적음

- 부모클래스는 java.io.InputStream, java.io.OutputStream

읽기 스트림 - InputStream
FileInputStream 파일에서 읽어 들이는 일
DatainputStream 자바의 기본 데이터형으로 읽어 들일 때
ObjectInputStream 객체를 읽어 들일 때

 

쓰기 스트림 - OutputStream
FileOutputStream 파일로 내보내는 일
DataOutputStream 자바의 기본 데이터형을 내보내는 일
ObjectOutputStream 객체를 내보내는 일

 

 2) 16bit Stream 

- 문자열 기반 스트림

- 문자열만 읽고 쓸 수 있는 스트림

- 문자열을 입력받기 위해서 고안한 Stream

- 8bit 보다 속도가 느림 / 단, 한 번에 보내고 받는 양은 큼

- 부모클래스는  java.io.Reader, java.io.Writer

읽기 스트림 - Reader
FileReader 파일에서 읽어 들이는 일
BufferedReader 16bit 스트림의 속도 향상을 위해 만들어진 Stream
InputStreamReader 8bit 스트림과 16bit 스트림을 연결할 때 사용

 

쓰기 스트림 - Writer
FileWriter 파일로 내보내는 일
BufferedWriter 쓰기속도 향상
OutputStreamWriter 8bit 스크림과 16bit 스트림을 연결할 때 사용

 

 

 2. java.io.File 

- HDD(하드디스크)에 존재하는 파일의 정보를 얻을 때, directory를 생성할 때, 파일 삭제할 때 사용

 

- 사용법)

 

<-- 파일 정보 -->

① 객체 생성 :

    File file = new File (“경로”); // C:/dev/env.bat

② 하기 method 활용

    - 절대경로 얻기 :

      > 파일에 접근할 수 있는 두가지 경로 : C:/dev/env.bat or c:/dev/env.bat – 드라이브 문자 대소문자 상관없음

      > String str = file.getAbsolutePath();

    - 규범경로 얻기 :

      > 파일에 접근할 수 있는 하나의 경로 : C:/dev/env.bat – 드라이브 문자 항상 대문자

      > try {String path = file.getCannonicalPath(); // IOException 존재하므로 try~catch

         } catch (IOException ie) {  }

    - 경로 얻기 : String path = file.getPath();

    - 디렉토리명 얻기 : String directory = file.getParent() ; // C:/dev/

    - 파일명 얻기 : String fileName = file.getName(); / env.bat

    - 파일인지? : boolean flag = file.isFile();

    - 폴더인지? : boolean flag = file.isDirectory();

    - 읽기 가능? : boolean flag = file.canRead();

    - 쓰기 가능? : boolean flag = file.canWrite();

    - 실행 가능? : boolean flag = file.canExecute();

    - 숨김파일 : boolean flag = file. isHidden();

    - 마지막 수정일자 : long modified = file.lastmodified();

    - 파일 있는지 : file.exists();

 

<-- Directory 생성 -->

① 객체 생성 : 생성할 폴더명을 가진 File 생성

    FIle file = new File (“e:/dev/temp1”)

② 폴더 생성 : 폴더가 존재하면 false 반환, 존재하지 않으면 폴더를 생성하고 true 반환

    file.mkdir(); // 상위폴더가 존재하지 않으면 폴더를 생성할 수 없음 // dev 폴더 없으면 생성 불가 

    file.mkdirs(); // 상위폴더가 존재하지 않으면 상위 폴더부터 폴더를 생성함 // dev부터 만들고 temp1 생성

 

<-- 파일 삭제 -->

① 삭제할 파일명으로 File을 생성

     File file = new File(“경로”);

② 파일 삭제

           file.delete();

 

<-- 파일명 변경 -->

① 원본 파일명으로 File을 생성

           File file = new File (“경로”);

② 변경할 파일명으로 File 생성

           File refile = new File (“변경할 경로”);

③ 변경할 이름을 설정 : file.renameTo(refile);

1. throws (예외 날림)

- method 뒤에 정의하여 method 안쪽에서 발생된 예외를 호출한 곳에서 처리하도록 할 때 사용

- method를 호출한 곳에서 예외를 처리함 (예외가 발생된 곳과 예외를 처리하는 코드를 분리할 수 있음)

- 예외를 날리면 method 안에서는 해당 예외를 try~catch로 처리할 필요가 없음

- method를 호출한 곳에서는 throws된 Exception을 try~catch

  or 또 다른 method로 throws

- 문법) method header의 가장 마지막에 정의

   public void test() throws 예외처리클래스명,,,(여러 개 가능)  {

    }

 

* throws 예외처리클래스명

 - CompileException/RumtimeException 다 가능

 - method 안에서 발생된 예외

 

* try ~ finally 문법 :

- method 안에서 같은 Exception이 여러 개 발생했을 때,

  method header에서 throws를 사용하면 method를 호출한 곳에서 한 번만 try~catch 처리하면 되므로

  method 내에서는 try문과 반드시 실행해야 할 finally문만 남게 됨

 

2. throw (예외 강제 발생)

- 개발자가 특정 상황에서 예외를 발생시켜 코드를 처리하는 방법

- 발생된 예외는 try~catch 또는 thorws(권장)로 처리 (throw는 throws로 처리하는 걸 권장)

- 사용자 정의 예외처리 클래스와 같이 사용됨

- 문법) throw new 예외처리클래스();

 

3. 사용자 정의 예외처리 클래스

- java에서 제공하는 예외처리 클래스가 현재 구현하는 업무에 부합되는 것이 없을 때,

  현재 업무에 맞는 예외처리 클래스를 제작하여 사용하는 것 (가독성향상)

 Ex) 로그인 실패 상황에 대한 예외처리 : FailedLoginException (java에서 예외 제공함)

     입금하는 일에 대한 예외처리 : java에서 제공하는 예외처리 클래스가 없음 (내가 만들자!)

- 작성법)

1. 내가 만든 클래스가 예외의 처리기능을 가지고 있어야 함 -> 상속으로 처리

2. Exception 만들기 (class naming : 업무명+Exception으로 naming  (Ex.TestException) )

- CompileException : Exception 상속

- RuntimeException : RuntimeException 상속

      Ex) public class TestException extends Exception or extends RuntimeException{  

           public TestException(){

           super(“예외가 발생했을 때 출력할 메시지”) }


# 오늘의 코딩 #

 - 초등학생일 경우에만 예외를 발생시켜보자

- 사용자 정의 예외처리 클래스를 작성하고, method에서 throw/throws한 다음 

  호출 시킨 곳에서 예외처리하기!

import java.util.Random;

/**
 * 사용자정의 예외처리 클래스를 사용해보자<br>
 * 초등학생은 예외발생시키기
 * @author user
 */
public class UseThrow {

	public String checkAge() throws AgeException{
		String result = "";

		String[] schoolGrade = {"초등학생","중학생","고등학생","대학생"};
		
		Random random = new Random();
		int flag = random.nextInt(schoolGrade.length);
		
		if(flag==0) {//초등학생인 경우 예외를 발생시킴
			throw new AgeException(schoolGrade[flag]+ " 입장불가 / 중학생 이상만 입장 가능합니다!");
		}// end if
		
		result = schoolGrade[flag] +" 입장 가능";
		return result;
	}//checkAge
	
	public static void main(String[] args) {
		UseThrow ut = new UseThrow();
		
		try {
			String result = ut.checkAge();
			System.out.println(result);
		} catch (AgeException e) {
			e.printStackTrace();
		}//end catch
		
	}//main

}//class

 

- 사용자 정의 예외처리 클래스는 간단하게 만든당

@SuppressWarnings("serial")
public class AgeException extends Exception {
	
	public AgeException() {
		this("어린이는 입장 불가합니다.");
	}// AgeException

	public AgeException(String msg) {
		super(msg);
	}// AgeException

}// AgeException

 

# 출력 결과 #

 

1) 초등학생이 아닌 경우 정상 처리 : 

대학생 입장 가능

2) 초등학생인 경우 예외 발생 :

AgeException: 초등학생 입장불가 / 중학생 이상만 입장 가능합니다!
at UseThrow.checkAge(UseThrow.java:19)
at UseThrow.main(UseThrow.java:30)

 

 

+ Recent posts