Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Share] Try-with-resources #5

Open
boohyunsik opened this issue Jan 17, 2020 · 5 comments
Open

[Share] Try-with-resources #5

boohyunsik opened this issue Jan 17, 2020 · 5 comments
Labels
Share This issue is about sharing things related with study

Comments

@boohyunsik
Copy link

Topic

3장 템플릿 첫 부분에 try-catch가 나와서 참고가 될 만한 try-with-resources에 대해 소개해드리고자 합니다.

Detail

Java를 이용해 외부 자원에 접근하는 경우 한가지 주의해야할 점은 외부자원을 사용한 뒤 제대로 자원을 닫거나 해제해야 한다는 점입니다.

public static void main(String[] args) {
	FileInputStream fis = null;
	try {
		fis = new FileInputStream("test.txt");
	} catch(IOException e) {
		System.out.println("error : " + e.getMessage());
	} finally {
		fis.close();
	}
}

그러나 위 코드에서 fis.close()IOException을 던지기 때문에 다음과 같은 코드가 됩니다.

public static void main(String[] args) {
	FileInputStream fis = null;
	try {
		fis = new FileInputStream("test.txt");
	} catch(IOException e) {
		System.out.println("error : " + e.getMessage());
	} finally {
		try {
			fis.close();
		} catch(IOException e) {
			// Handle error...
		}
	}
}

또한 test.txt 파일이 없는 경우는 fisnull 일 것이기 때문에 null check도 해줘야 합니다.

public static void main(String[] args) {
	FileInputStream fis = null;
	try {
		fis = new FileInputStream("test.txt");
	} catch(IOException e) {
		System.out.println("error : " + e.getMessage());
	} finally {
		try {
			if (fis != null) {
				fis.close();
			}
		} catch(IOException e) {
			// Handle error...
		}
	}
}

코드가 매우 지저분해집니다. 이를 해결하기 위해 JDK 1.7부터는 다음과 같은 인터페이스가 추가되었습니다.

/**
 * @author Josh Bloch
 * @since 1.7
 */
public interface AutoCloseable {
    void close() throws Exception;
}

(저자 Josh Bloch는 Effective Java의 저자입니다.)
이 인터페이스 추가와 더불어 try절에 소괄호가 들어가는 문법이 추가되었습니다.

try(FileInputStream fis = new FileInputStream("test.txt") {
	// Do something if success
} catch(IOException e) {
	// Handle error...
}

다음과 같이 깔끔하게 코드를 작성할 수 있고, close()를 호출하지 않아도 성공적으로 실행했을때나, Exception이 발생했을때 모두 자원을 해제할 수 있습니다.

@boohyunsik boohyunsik added the Share This issue is about sharing things related with study label Jan 17, 2020
@ttkmw
Copy link

ttkmw commented Jan 22, 2020

이제 봤는데 내용 좋네요
몰랐습니다..

공유 감사해요!

@sojeongw
Copy link

오 신기하네요. 완전 꿀팁!

@hihiboss
Copy link
Member

좋은 글 감사합니다!
신기해서 try-with-resource statement에 대해 찾아보다가 추가 내용이 있어 공유합니다!

  1. try-with-resourcetry에 자원 객체(AutoCloseable 인터페이스를 구현한 객체)를 전달하여 try 코드 블록이 끝나면 자동으로 자원을 종료함.
try (SomeResource resource = getResource()) {
    use(resource);
} catch(...) {
    ...
}
  1. try() 안에 여러 개의 자원 객체를 전달할 수 있음.
try(Something1 s1 = new Something1();
    Something2 s2 = new Something2()) {
    ...
} catch(...) {
    ...
}
  1. try 블록과 finally 블록에서 동시에 예외가 발생했을 경우, 기존 try-catch-finally 구문은 finally 블록에서 발생한 예외를 throw 하지만, try-with-resource 구문은 try 블록의 예외를 throw 함.
static String useTry(String path) throws IOException {
    BufferedReader br = new BufferedReader(new FileReader(path));
    try {
        return br.readLine();
    } finally {
        if (br != null) br.close();
    }
}

위 코드에서

    try {
        return br.readLine();
    } 

이 부분(br.readLine())과

    finally {
        if (br != null) br.close();
    }

이 부분(br.close())에서 동시에 예외 발생할 수 있음. 이런 경우 br.close()의 예외를 throw 함.

그러나 try-with-resource 구문은 다름.

static String useTryResource(String path) throws IOException {
    try (BufferedReader br = new BufferedReader(new FileReader(path))) {
        return br.readLine();
    }
}

위 코드에서

    return br.readLine();

try 블럭 부분(br.readLine())과

    try (BufferedReader br = new BufferedReader(new FileReader(path)))

try resource 부분(new FileReader())에서 동시에 예외 발생할 수 있음. 이런 경우 br.readLine()의 예외를 throw 함.

@hea9549
Copy link
Member

hea9549 commented Jan 27, 2020

@hihiboss 마지막 3번에서 br.readline() 에러가아니라 new FileReader()의 exception 을 throw하는게 맞지않앙??

@hea9549
Copy link
Member

hea9549 commented Jan 27, 2020

그리고 다들 봣을수있지만 위의 예제처럼 중첩접근에서의 close() 호출순서에대해서
https://multifrontgarden.tistory.com/192
여기 잘나와있어요~ autocloseable 을 impl 할일 있거나 close가 어떻게 각각 일어나는지 궁금하면 참고 하세요

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Share This issue is about sharing things related with study
Projects
None yet
Development

No branches or pull requests

5 participants