Java 개발을 하다보면 close 메서드를 호출해 자원을 해제해줘야하는 자원을 마주하게된다. 만약 프로그램에서 사용한 자원을 해제하지 않아 독점하게되면 운영체제의 자원이 고갈되어 다른 프로그램은 자원을 사용하지 못하게되는 결과를 초래하기 때문이다.
- Scanner
- BufferedReader
- FileInputStream
- FileOutputStream
- BufferedInputStream
- BufferedOutpusStream
- 기타 등등
위와 같은 자원을 사용 객체들은 try-catch-finally 블록에서 자원을 사용하고 해제해야만한다.
예를 들어, 텍스트 파일을 읽어 콘솔에 출력하는 코드는 아래와 같이 작성해 자원을 반드시 해제시켜야한다.
public class Test
{
public static void main(String args[])
{
FileInputStream fis = null;
BufferedInputStream bis = null;
try
{
fis = new FileInputStream("test.txt");
bis = new BufferedInputStream(fis);
while( bis.available() > 0 )
{
System.out.print((char)bis.read());
}
}
catch(IOException e)
{
...
}
finally
{
try
{
if(bis != null)
{
bis.close();
}
if(fis != null)
{
fis.close();
}
}
catch(IOException ioe)
{
...
}
}
}
}
하나의 기능만 수행하는 아주 간단한 로직이지만, try-catch-finally 구문으로 인해 코드가 매우 복잡하다.
- try 블록에서 Exception이 발생할 수 있으므로 finally 블록에서 자원을 해제해야함
- 자원 해제 전 FileInputStream, BufferedInputStream 객체가 null 인지 여부를 체크해야함
- 자원을 해제할 때 발생할 수 있는 예외도 처리해줘야함
Try-with-Resources
Java 7 부터는 Try-with-Resources 구문이 지원되어 기존의 방식보다 훨씬 쉽게 자원을 해제할 수 있다.
아래는 위 코드를 try-with-resources 구문으로 변경한 코드이다.
public class Test
{
public static void main(String args[])
{
try(
FileInputStream fis = new FileInputStream("test.txt");
BufferedInputStream bis = new BufferedInputStream(fis);
){
while( bis.available() > 0 )
{
System.out.print((char)bis.read());
}
}
catch(IOException e)
{
...
}
}
}
try(...) 괄호 안에 자원을 사용하는 객체를 초기화하면, 그 객체들은 try 구문 안에서 사용이 가능하다.
그리고 코드가 try 블록을 벗어나면 자동으로 try(...) 괄호 안에 선언된 객체들에 대해 close() 메서드를 호출해 자원을 해제시킨다.
때문에 기존과 같이 finally 블록에서 close() 메서드를 명시적으로 호출할 필요가 없다.
Try-with-Resources 의 장점
- 코드가 간결해진다
- 자원 해제가 자동으로 처리되므로 버그가 발생할 확률이 낮다
Try-with-Resources 를 사용할 수 있는 객체
=> AutoCloseable 인터페이스를 구현한 객체
- AbstractInterruptibleChannel
- AbstractSelectableChannel
- AbstractSelector
- AsynchronousFileChannel
- AsynchronousServerSocketChannel
- AsynchronousSocketChannel
- AudioInputStream
- BufferedInputStream
- BufferedOutputStream
- BufferedReader
- BufferedWriter
- ByteArrayInputStream
- ByteArrayOutputStream
- CharArrayReader
- CharArrayWriter
- CheckedInputStream
- CheckedOutputStream
- CipherInputStream
- CipherOutputStream
- DatagramChannel
- DatagramSocket
- DataInputStream
- DataOutputStream
- DeflaterInputStream
- DeflaterOutputStream
- DigestInputStream
- DigestOutputStream
- FileCacheImageInputStream
- FileCacheImageOutputStream
- FileChannel
- FileImageInputStream
- FileImageOutputStream
- FileInputStream
- FileLock
- FileOutputStream
- FileReader
- FileSystem
- FileWriter
- FilterInputStream
- FilterOutputStream
- FilterReader
- FilterWriter
- Formatter
- ForwardingJavaFileManager
- GZIPInputStream
- GZIPOutputStream
- ImageInputStreamImpl
- ImageOutputStreamImpl
- InflaterInputStream
- InflaterOutputStream
- InputStream
- InputStreamReader
- JarFile
- JarInputStream
- JarOutputStream
- LineNumberInputStream
- LineNumberReader
- LogStream
- MemoryCacheImageInputStream
- MemoryCacheImageOutputStream
- MLet
- MulticastSocket
- ObjectInputStream
- ObjectOutputStream
- OutputStream
- OutputStreamWriter
- Pipe.SinkChannel
- Pipe.SourceChannel
- PipedInputStream
- PipedOutputStream
- PipedReader
- PipedWriter
- PrintStream
- PrintWriter
- PrivateMLet
- ProgressMonitorInputStream
- PushbackInputStream
- PushbackReader
- RandomAccessFile
- Reader
- RMIConnectionImpl
- RMIConnectionImpl_Stub
- RMIConnector
- RMIIIOPServerImpl
- RMIJRMPServerImpl
- RMIServerImpl
- Scanner
- SelectableChannel
- Selector
- SequenceInputStream
- ServerSocket
- ServerSocketChannel
- Socket
- SocketChannel
- SSLServerSocket
- SSLSocket
- StringBufferInputStream
- StringReader
- StringWriter
- URLClassLoader
- Writer
- XMLDecoder
- XMLEncoder
- ZipFile
- ZipInputStream
- ZipOutputStream
반응형
'☕️ JAVA' 카테고리의 다른 글
SXSSFWorkbook 생성 시 FontConfiguration에서 NullPointerException이 발생할 때 (0) | 2021.11.25 |
---|---|
[자바로 배우는 리팩토링 입문] 리팩토링이란? (0) | 2021.08.15 |
BufferedReader 가 Scanner 보다 빠른 이유 (0) | 2020.11.08 |
Enum을 사용해보자 (0) | 2020.10.18 |
WebSocketSession에서 HttpSession를 얻는 방법 (0) | 2020.09.10 |