finalize 메서드, 닫을 수 있는 인터페이스 및 리소스를 사용하여 시도하는 문(Java 7) - 1

"안녕, 아미고!"

"방금 finalize () 메서드에 대해 논의하기로 했습니다 ."

"기억하시겠지만 finalize()는 가비지 컬렉터가 객체를 파괴하기 전에 객체가 호출하는 특수 메서드입니다."

"이 방법의 주요 목적은 파일, I/O 스트림 등을 닫아 사용된 외부 비Java 리소스를 확보하는 것입니다."

"안타깝게도 이 방법은 우리의 기대에 부응하지 못합니다. JVM(Java Virtual Machine)은 원하는 만큼 객체 파괴 및 종료 방법 호출을 연기할 수 있습니다. 전혀 호출되지 않습니다. 모두 «최적화»라는 이름으로 호출되지 않는 상황이 많이 있습니다."

"두 가지 참고 자료가 있습니다."

Joshua Bloch 는 이 방법에 대한 좋은 기사를 작성했습니다
.

  1. finalize()는 두 가지 경우에만 사용할 수 있습니다.
    1. 로깅을 통해 리소스를 확인하거나 정리합니다.
    2. 리소스 누수에 중요하지 않은 네이티브 코드로 작업할 때.
  2. finalize()는 개체 정리 시 GC를 430배 느리게 만듭니다.
  3. finalize()가 호출되지 않을 수 있습니다.
인터뷰에서 Finalize는 존재 자체가 혼란스러운 해롭고 위험한 목발이라고 말하면 맞습니까?

"음, 그게 내 하루를 만들었어, 엘리."

"Java 7에는 finalize 메서드를 대체하는 새로운 명령문이 있습니다 . try-with-resources 라고 합니다 . 실제로 finalize를 대체하는 것이 아니라 대체 접근 방식입니다."

"try-catch와 같지만 리소스가 있습니까?"

"거의 try-catch 와 비슷합니다 . finalize () 메서드 와 달리 try- catch-finally 문의 finally 블록은 항상 실행됩니다. 프로그래머도 리소스를 확보해야 할 때 이 기술을 사용했습니다. 스레드 닫기 등
 "여기에 예가 있습니다."

InputStream is = null;
try
{
 is = new FileInputStream("c:/file.txt");
 is.read(…);
}
finally
{
 if (is != null)
 is.close();
}

" try 블록이 제대로 실행되었는지 또는 예외가 있었는지 에 관계없이 finally 블록은 항상 호출되며 거기에서 점유된 리소스를 해제할 수 있습니다."

"그래서 Java 7에서는 다음과 같이 이 접근 방식을 공식화하기로 결정했습니다."

try(InputStream is = new FileInputStream("c:/file.txt"))
{
 is.read(…);
}

"이 특별한 try 문 은 try-with-resources 라고 합니다 (컬렉션에 foreach 라는 대안이 있는 것과 유사함 )."

"try 다음에 변수가 선언되고 개체가 생성되는 괄호가 있다는 점에 유의하십시오. 이러한 개체는 중괄호로 표시된 try 블록 내에서 사용할 수 있습니다. try 블록이 완료되면 정상적으로 종료되었는지 여부에 관계없이 실행됩니다. 예외인 경우 close() 메서드는 괄호 안에 생성된 모든 객체에서 호출됩니다."

"흥미롭다! 이 표기법은 이전 표기법보다 훨씬 간단하다. 아직 이해하지 못했다."

"생각보다 어렵지 않습니다."

"그러면 괄호 안에 각 개체의 클래스를 지정할 수 있습니까?"

"예, 물론입니다. 그렇지 않으면 괄호가 거의 쓸모가 없을 것입니다."

"그리고 try 블록을 종료한 후 다른 메서드를 호출해야 하는 경우 어디에 두어야 합니까?"

"여기서 상황은 좀 더 미묘합니다. Java 7에는 다음 인터페이스가 도입되었습니다."

public interface AutoCloseable
{
 void close() throws Exception;
}

"귀하의 클래스는 이 인터페이스를 구현할 수 있습니다. 그런 다음 try-with-resources 문 내에서 해당 개체를 사용할 수 있습니다. «자동 종료»에 대한 try-with-resources 문의 괄호 안에 이러한 개체만 만들 수 있습니다."

"즉, close 메서드를 재정의하고 개체를 «정리»하는 코드를 작성해야 하는데 다른 메서드를 지정할 수 없습니까?"

"예. 하지만 여러 개체를 지정할 수 있습니다. 세미콜론으로 구분하기만 하면 됩니다."

try(
InputStream is = new FileInputStream("c:/file.txt");
OutputStream os = new FileOutputStream("c:/output.txt")
)
{
 is.read(…);
 os.write(…);
}

"그게 낫긴 한데, 내가 기대했던 것만큼 멋지지는 않군."

"그렇게 나쁘지는 않아. 익숙해질 거야. 시간이 지나면."