Java에 using 문이 있습니까?


107

Java에는 최대 절전 모드에서 세션을 열 때 사용할 수있는 using 문이 있습니까?

C #에서는 다음과 같습니다.

using (var session = new Session())
{


}

따라서 개체가 범위를 벗어나 자동으로 닫힙니다.


4
"객체에 대한 범위 정의 허용"그게 무슨 일 이냐 using. 범위는 수명이 아닙니다 ( using엄밀히 말하면 Dispose객체의 기억을 파괴하지 않는 것처럼 수명에 관한 것도 아닙니다.)
Joren

4
@Joren 귀하의 의견이 찬성 투표를 받고 있지만 좀 더 많은 정보로 할 수 있습니다. 당신은 "평생"아이디어를 소개하는 사람이고 "평생"에 관한 것이 아니라고 말합니다. 범위는 msdn 라이브러리의 정의에 사용 된 용어입니다. 내가 잘못 사용했을 수도 있습니다. 당신은을 정의 할 방법 using statement.
Jla

1
범위는 완전한 이름 (로컬 변수, 유형, 메소드 이름 등)을 사용하지 않고 식별자를 참조 할 수있는 코드의 영역을 나타냅니다. 수명은 개체 또는 변수에 액세스 할 수있는 시간을 나타냅니다. blogs.msdn.com/b/ericlippert/archive/2009/08/03/…
Joren

2
예를 들어 지역 변수가 있고 여기에 값 유형 인스턴스를 할당하면 변수의 수명이 끝날 때 값의 수명이 끝납니다. 그러나 객체를 할당하고 그에 대한 참조를 로컬에 저장 한 경우 다른 곳에 객체에 대한 참조가있는 한 해당 객체의 수명은 해당 저장소의 수명을 지나서 매우 잘 연장 될 수 있습니다. 에 관해서는 using, 자동 처분 의 범위의 끝 부분에있는 객체를,하지만하지 않습니다 할당 해제 객체를 - 모든 참조가 사라질 때까지 수명이 끝나지 않았습니다.
Joren

답변:


124

Java 7 은이 기능을 Java 플랫폼에 제공하는 자동 리소스 블록 관리 를 도입했습니다 . 이전 버전의 Java에는 using.

예를 들어 java.lang.AutoCloseable다음과 같은 방식으로 구현하는 모든 변수를 사용할 수 있습니다 .

try(ClassImplementingAutoCloseable obj = new ClassImplementingAutoCloseable())
{
    ...
}

java.io.Closeable스트림으로 구현 된 Java의 인터페이스는 자동으로 확장 AutoCloseable되므로 tryC # using블록 에서 사용하는 것과 동일한 방식으로 블록에서 스트림을 이미 사용할 수 있습니다 . 이것은 C #의 using.

현재 버전 5.0, 최대 절전 모드 세션 구현AutoCloseable 및 ARM 블록에 자동으로 폐쇄 될 수 있습니다. 이전 버전의 Hibernate SessionAutoCloseable 에서는 . 따라서이 기능을 사용하려면 Hibernate> = 5.0에 있어야합니다.


1
"다행히"현재 Java 7을 사용할 수있게되면서이 대답은 더 이상 사실이 아닙니다 (그리고 ARM 블록 이 정확히 하는 일 이라고 생각합니다 using).
Joachim Sauer

@Joachim Sauer : 감사합니다. 시간의 흐름을 반영하여 답변을 업데이트했습니다. ARM 블록이 정확히 무엇을 사용하는지에 대한 관점에서; 이 답변을 작성했을 때 ARM 블록은 try 블록이어야하는 것처럼 보였지만 using은 임의의 블록에 적용될 수 있습니다. 지금 보면 자바에서 do 키워드를 사용하여이를 수행 할 수있는 것처럼 보입니다. 최근에 제안에 추가 되었습니까? 아니면 처음에 놓쳤습니까? 또한 OP는 Hibernate 세션에 대해 구체적으로 물었습니다. AFAIK : Hibernate Sessions는 아직 구현 AutoCloseable되지 않았으므로 아직 ARM을 사용할 수 없습니다.
Asaph

1
4.3 Hibernate의 Not 이벤트는 AutoCloseable을 구현 하지 않습니다 . docs.jboss.org/hibernate/orm/4.3/javadocs/index.html?org/… 자신의 래퍼를 작성하는 것은 모든 사람에게 달려 있다고 생각합니까?
Andrei Rînea 2013

1
Session.close ()가 연결을 반환하므로 세션은 AutoCloseable을 구현할 수 없습니다. 나는 이것이 나쁜 디자인이라고 생각하지만 이것이 변경 될 것 같지 않습니다.
usr-local-ΕΨΗΕΛΩΝ 2014 년

@ usr-local-ΕΨΗΕΛΩΝ 나는 그들이 그 인터페이스를 구현한다면 자바 7로 전환하기 위해 최대 절전 모드를 사용하는 사람에게 의무가 있다고 생각했습니다. AutoCloseableJava 7 이전에는 존재하지 않았습니까?
Neil

31

Java 7 이전에는 Java에 이러한 기능 이 없었 습니다 (Java 7 이상에서는 ARM 에 관한 Asaph 의 답변 참조 ).

수동으로해야 했는데 고통 스러웠습니다 .

AwesomeClass hooray = null;
try {
  hooray = new AwesomeClass();
  // Great code
} finally {
  if (hooray!=null) {
    hooray.close();
  }
}

그리고 그것은 예외를 던질 수도 // Great code없고 hooray.close()던질 수도 없는 코드 일뿐 입니다.

정말로 변수의 범위를 제한하려는 경우 간단한 코드 블록이 작업을 수행합니다.

{
  AwesomeClass hooray = new AwesomeClass();
  // Great code
}

그러나 그것은 아마도 당신이 의미 한 것이 아닐 것입니다.


1
// Great code예외가 발생하더라도 Java에 해당하는 것은 문제가되지 않습니다 .
Cheeso

3
생성자가 예외를 throw하면 코드가 원래 예외를 마스킹하는 NullPointerException이 발생할 것이라고 생각합니다.
Michael Borgwardt

@Michael : 실제로 내 예제는 컴파일 horray되지 않을 것입니다. 그 시점에서 초기화되지 않았을 수도 있기 때문 입니다 (지금 수정 됨).
Joachim Sauer

4
범위를 제한 할 수있는 부동 단순 블록의 경우 +1입니다. 그러나 내가 이것을 볼 때마다 거의 항상 메서드가 더 작은 덩어리로 나뉘어 야한다는 지표입니다.
Mark Peters

1
생성자에서 예외를 포착하려면 try 블록 안에 있어야합니다. 모든 것을 다른 try / catch로 포장하는 것은 번거 롭습니다.
ths



8

가장 가까운 자바에 해당하는 것은

AwesomeClass hooray = new AwesomeClass();
try{
    // Great code
} finally {
    hooray.dispose(); // or .close(), etc.
}



2

리소스 관리에 관심이있는 경우 Project Lombok 에서 @Cleanup주석을 제공합니다 . 사이트에서 직접 가져옴 :

를 사용 @Cleanup하여 코드 실행 경로가 현재 범위를 벗어나기 전에 지정된 리소스가 자동으로 정리되도록 할 수 있습니다 . 다음 @Cleanup 과 같은 주석으로 지역 변수 선언에 주석을 달면됩니다.

@Cleanup InputStream in = new FileInputStream("some/file");

결과적으로 사용자가 속한 범위의 끝에서이 in.close()호출됩니다. 이 호출은 try / finally 구성을 통해 실행됩니다. 이것이 어떻게 작동하는지 아래의 예를보십시오.

정리하려는 객체 유형에 close() 메서드가 없지만 인수가없는 다른 메서드가있는 경우 다음과 같이이 메서드의 이름을 지정할 수 있습니다.

@Cleanup("dispose") org.eclipse.swt.widgets.CoolBar bar = new CoolBar(parent, 0);

기본적으로 정리 방법은 close(). 인수를받는 정리 메서드는를 통해 호출 할 수 없습니다 @Cleanup.

바닐라 자바

import java.io.*;

public class CleanupExample {
  public static void main(String[] args) throws IOException {
    InputStream in = new FileInputStream(args[0]);
    try {
      OutputStream out = new FileOutputStream(args[1]);
      try {
        byte[] b = new byte[10000];
        while (true) {
          int r = in.read(b);
          if (r == -1) break;
          out.write(b, 0, r);
        }
      } finally {
        out.close();
      }
    } finally {
      in.close();
    }
  }
}

롬복과 함께

import lombok.Cleanup;
import java.io.*;

public class CleanupExample {
  public static void main(String[] args) throws IOException {
    @Cleanup InputStream in = new FileInputStream(args[0]);
    @Cleanup OutputStream out = new FileOutputStream(args[1]);
    byte[] b = new byte[10000];
    while (true) {
      int r = in.read(b);
      if (r == -1) break;
      out.write(b, 0, r);
    }
  }
}


1

Java 키워드 목록을 참조하십시오 .

  1. using키워드는 불행하게도 목록의 일부가 아닙니다.
  2. 또한 using현재 Java에서와 같이 다른 키워드를 통해 C # 키워드 와 동등하지 않습니다 .

이러한 "using"동작 을 모방하려면 try...catch...finally블록 을 사용해야합니다 . 여기서 finally.


6
using키워드가 아니라는 사실 은 의미가 없습니다. @BalusC가 언급했듯이 동일한 기능을 다른 키워드로 구현할 수 있습니다.
Joachim Sauer

1
나는 동의한다! 하지만 지금은 존재하지 않습니다. 그것이 바로 지금 비슷한 것이 있다면 OP가 요청한 것입니다. 향후 릴리스에 존재할 것이라는 점을 아는 것이 좋지만 현재로서는 어떤 방식 으로든 변경되지 않습니다. 어쨌든 @BalusC에서 제공하는 정보는 훌륭합니다! =)
Will Marcouiller

2
동의하지만 귀하의 게시물 using은 Java 키워드 목록에 없다는 사실이이 기능이 Java 언어로 제공되지 않는다는 것을 의미 한다고 말하는 것 같습니다 . 그리고 그것은 사실이 아닙니다.
Joachim Sauer

이것이 내 게시물이 말하는 것처럼 보인다면 내 의도를 반영하도록 편집 할 것입니다.
Will Marcouiller

나는 using키워드 가 없으며 현재로서는 동등하지 않다는 것을 명시하여 내 대답을 편집했습니다 . 감사합니다 @Joachim Sauer! =)
Will Marcouiller


0

변수 자동 닫기 / 삭제에 대해 이야기하는 대신 변수 범위 제한에 관한 질문에 대답합니다.

Java에서는 중괄호를 사용하여 닫힌 익명 범위를 정의 할 수 있습니다. 매우 간단합니다.

{
   AwesomeClass hooray = new AwesomeClass()
   // Great code
}

변수 hooray는이 범위에서만 사용할 수 있으며 외부에서는 사용할 수 없습니다.

이것은 일시적인 반복 변수가있는 경우 유용 할 수 있습니다.

예를 들어, 각각 인덱스가 있습니다. item변수가 for 루프에서 닫히는 것처럼 (즉, 내부에서만 사용 가능함) index변수는 익명 범위에서 닫힙니다.

// first loop
{
    Integer index = -1;
    for (Object item : things) {index += 1;
        // ... item, index
    }
}

// second loop
{
    Integer index = -1;
    for (Object item : stuff) {index += 1;
        // ... item, index
    }
}

변수 범위를 제공하는 for 루프가 없지만 일반 변수 이름을 사용하려는 경우에도 가끔 사용합니다.

{
    User user = new User();
    user.setId(0);
    user.setName("Andy Green");
    user.setEmail("andygreen@gmail.com");
    users.add(user);
}

{
    User user = new User();
    user.setId(1);
    user.setName("Rachel Blue");
    user.setEmail("rachelblue@gmail.com");
    users.add(user);
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.