어제 오늘 내일

[Java] Try with resources 로 자원 반납하기 본문

IT/Java

[Java] Try with resources 로 자원 반납하기

hi.anna 2021. 5. 1. 06:45

Java 7 버전 이전에는

다 사용하고 난 자원(resource)을 반납하기 위해서

try-catch-finally 구문을 사용했었습니다.

 

Java 7버전 이후에 추가된 try with resources 기능은

try 구문에 리소스를 선언하고,

리소스를 다 사용하고 나면 자동으로 반납(close) 해주는 기능입니다.

java.lang.AutoCloseable 인터페이스를 구현하는 객체가

try with resources의 resource로 사용될 수 있습니다.

 

 

try-catch-finally 

 리소스 생성/반납하기 

[ 코드 ]

import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;

public class ResourceClose {
    public static void main(String[] args) {
        Scanner scanner = null;
        try {
            // scanner 생성
            scanner = new Scanner(new File("input.txt"));
            System.out.println(scanner.nextLine());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            // scanner 리소스 반납
            if (scanner != null) {
                scanner.close();
            }
        }
    }
}

기존(Java 7이전)에 try-catch-finally 구문을 이용하여

리소스를 생성하고, 반납하는 코드입니다.

리소스의 생성은 try 구문에서, 리소스의 반납은 finally 구문에서 하다보니,

리소스를 생성하고, 반납을 빼먹는 경우가 종종 발생했습니다.

 

 

 

try with resources 

 리소스 생성/반납하기 

[ 코드 ]

import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;

public class ResourceClose {
    public static void main(String[] args) {
        try (Scanner scanner = new Scanner(new File("input.txt"))) {
            System.out.println(scanner.nextLine());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
}

Java 7 이후에는 try with resources를 이용하여, 

리소스를 생성하고, 자동으로 반납합니다.

위 코드는, try-catch-finally 구문으로 리소스를 생성하고 반납했던 앞의 예제와 같은 내용입니다.

 

try(Scanner scanner = new Scanner(new File("input.txt")))

try-catch-finally 구문과 달리

try옆에 괄호안에서 리소스를 생성합니다.

그리고, 어느 곳에서도 생성된 리소스를 반납하는 코드가 없습니다.

try with resources 구문을 사용하면 자동으로 리소스가 반납됩니다.

 

try with resources 구문에 사용 되는 리소스는 (try옆의 괄호 안에서 정의 될수 있는 리소스)

반드시 java.lang.AutoCloseable 인터페이스를 구현해야 합니다.

예제에 사용된, Scanner 클래스도 AutoCloseable 인터페이스가 구현되어 있습니다.

 

 여러개의 리소스 생성 반납 

[ 코드 ]

import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.Scanner;

public class ResourceClose {
    public static void main(String[] args) {
        try (Scanner scanner = new Scanner(new File("input.txt"));
                PrintWriter pw = new PrintWriter(new File("output.txt"))) {
            System.out.println(scanner.nextLine());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
}

여러 개의 리소스를 같이 생성하고 반납할 수도 있습니다.

try에서 리소스를 생성할 때, 위 예제와 같이 ';'로 구분하여

여러 리소스를 생성할 수 있습니다.

 

 Custom Resource 생성하기 - AutoCloseable 

AutoCloseable 인터페이스를 구현하여, 사용자가 리소스 클래스를 생성할 수도 있습니다.

 

[ 코드 ]

public class CustomResource implements AutoCloseable {

    public CustomResource() {
        System.out.println("CustomResource Constructor");
    }

    public void printMessage() {
        System.out.println("CustomResource Print Message");
    }

    @Override
    public void close() throws Exception {
        System.out.println("CustomResource close");

    }
}
public class ResourceClose {
    public static void main(String[] args) {
        try (CustomResource cr = new CustomResource()) {
            cr.printMessage();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

[ 결과 ]

CustomResource Constructor
CustomResource Print Message
CustomResource close

위 예제는 AutoCloseable 인터페이스를 구현하여, CustomResource 클래스를 생성하고

try with resources 구문에서 CustomResource 클래스를 사용하는 예제입니다.

 

CustomResource 클래스

- AutoCloseable 인터페이스를 구현하였습니다.

- AutoCloseable 인터페이스에 정의된 close() 메소드를 Override 하여 구현하였습니다.

 

ResourceClose 클래스

- try with resources 구문에 사용자가 직접 만든 CustomResource 클래스를 사용하였습니다.

- close()를 따로 호출하지 않았지만, 자동으로 호출되어 "CustomResource close" 메세지가 출력되었습니다.

 

 

 리소스 반납 순서 

여러개의 리소스가 같이 선언되었을 경우에는

나중에 선언된 리소스부터 close(반납) 됩니다.

 

[ 코드 ]

public class CustomResource1 implements AutoCloseable {

    public CustomResource1() {
        System.out.println("CustomResource Constructor_1");
    }

    public void printMessage() {
        System.out.println("CustomResource Print Message_1");
    }

    @Override
    public void close() throws Exception {
        System.out.println("CustomResource close_1");

    }
}
public class CustomResource2 implements AutoCloseable {

    public CustomResource2() {
        System.out.println("CustomResource Constructor_2");
    }

    public void printMessage() {
        System.out.println("CustomResource Print Message_2");
    }

    @Override
    public void close() throws Exception {
        System.out.println("CustomResource close_2");

    }
}
public class ResourceClose {
    public static void main(String[] args) {
        try (CustomResource1 cr1 = new CustomResource1(); CustomResource2 cr2 = new CustomResource2()) {
            cr1.printMessage();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

[ 결과 ]

CustomResource Constructor_1
CustomResource Constructor_2
CustomResource Print Message_1
CustomResource close_2
CustomResource close_1

위 예제에서

ResourceClose 클래스는

CustomResource1, CustomResource2 이렇게 2개의 리소스를 순서대로 생성하였습니다.

 

결과를 보면,

리소스 생성은 CustomResource1, CustomResource2 순서로 되었지만,

리소스 자원 반납(close)는 CustomResource2, CustomResource1 순서로 된 것을 확인 할 수 있습니다.

 


 

Java 7 이후에 추가된

자동으로 자원을 반납하는 try with resources에 대해서 알아보았습니다.

 

 

반응형
Comments