Java'nın bir using ifadesi var mı?


108

Java, hazırda bekletme modunda bir oturumu açarken kullanılabilecek bir using deyimine sahip mi?

C # 'da şuna benzer:

using (var session = new Session())
{


}

Böylece nesne kapsam dışına çıkar ve otomatik olarak kapanır.


4
"Bir nesne için bir kapsam tanımlamaya izin verme" Bu, ne usingişe yarar. Kapsam ömür boyu değildir (ve usingkesinlikle Disposebir nesnenin hafızasını yok etmediği için yaşam süresiyle de ilgili değildir.)
Joren

4
@Joren Yorumunuz oylanıyor ama biraz daha bilgi verebilirim. "Yaşam boyu" fikrini ortaya atan sensin, sonra bunun "yaşamla" ilgili olmadığını söylüyorsun. Kapsam, msdn kitaplığındaki tanımda kullanılan terimdir, belki de yanlış kullandım. Eğer tanımlarsınız nasıl using statement.
Jla

1
Kapsam, bir tanımlayıcıya tam olarak nitelenmiş adını (yerel değişken, tür, yöntem adı ve benzeri) kullanmadan başvurabileceğiniz koddaki alanı ifade eder. Yaşam süresi, bir nesnenin veya değişkenin erişilebilir olduğu zamanı ifade eder. Bkz. Blogs.msdn.com/b/ericlippert/archive/2009/08/03/…
Joren

2
Örneğin, yerel bir değişkeniniz varsa ve ona bir değer türü örneği atarsanız, değerinizin ömrü, değişkeninin ömrü sona erdiğinde sona erer. Ancak bir nesneyi tahsis ettiyseniz ve ona bir referansı yerelde depoladıysanız, o nesnenin ömrü, başka bir yerde nesneye bir miktar referans olduğu sürece, depolamanın ömrünü çok iyi bir şekilde aşabilir. Buna gelince , nesneyi kapsamının sonuna usingotomatik olarak atar , ancak nesneyi serbest bırakmaz - tüm referansları ortadan kalkana kadar ömrü bitmez.
Joren

1

Yanıtlar:


125

Java 7 , bu özelliği Java platformuna getiren Otomatik Kaynak Blok Yönetimini tanıttı . Java'nın önceki sürümlerinde benzer hiçbir şey yoktu using.

Örnek olarak, herhangi bir değişkeni java.lang.AutoCloseableaşağıdaki şekilde uygulayabilirsiniz :

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

Java'nın java.io.Closeableakışlar tarafından uygulanan arabirimi otomatik olarak genişler AutoCloseable, böylece akışları bir trybloktaki akışları bir C # usingbloğunda kullandığınız gibi zaten kullanabilirsiniz . Bu, C # 'lara eşdeğerdir using.

İtibariyle sürüm 5.0, hazırda Oturumları uygulamakAutoCloseable ve ARM bloklar halinde otomatik kapalı olabilir. Hibernate Session'ınAutoCloseable önceki sürümlerinde uygulanmıyordu . Bu özelliği kullanmak için Hazırda Bekleme> = 5.0 konumunda olmanız gerekir.


1
"Şans eseri" şu anda mevcut olan Java 7 ile bu yanıt artık doğru değil (ve ARM bloklarının tam olarak ne olduğunu düşünüyorum using).
Joachim Sauer

@Joachim Sauer: Teşekkürler. Cevabımı zamanın geçişini yansıtacak şekilde güncelledim. Sizin açınızdan ARM blokları tam olarak ne kullanırsa; bu cevabı yazdığım zaman, bana ARM bloklarının deneme blokları olması gerektiği gibi görünüyordu, oysa kullanımı herhangi bir rastgele bloğa uygulanabilir. Şimdi baktığımızda, do anahtar sözcüğü java'da bunu başarmak için kullanılabilir gibi görünüyor. Bu son zamanlarda teklife eklendi mi yoksa ilk defa mı kaçırdım? OP ayrıca özellikle Hazırda Bekletme Oturumları hakkında sorular sordu. AFAIK: Hazırda Bekletme Oturumları hala uygulanmadığından AutoCloseablehenüz ARM kullanamazlar.
Asaph

1
4.3 Hazırda Bekletme'de olay değil AutoCloseable UYGULAMAMAKTADIR. docs.jboss.org/hibernate/orm/4.3/javadocs/index.html?org/… Sanırım kendi sarmalayıcısını yazmak herkesin görevi?
Andrei Rînea

1
Session.close () bir Bağlantı döndürdüğünden, oturum AutoCloseable'ı uygulayamaz. Bunun kötü bir tasarım olduğunu düşünüyorum ama bunun hiç değişmeyeceğinden şüpheliyim.
usr-local-ΕΨΗΕΛΩΝ

@ usr-local-ΕΨΗΕΛΩΝ Sadece bu arayüzü uyguladılarsa, hazırda bekletmeyi kullanan herkesi java 7'ye geçmeye mecbur edeceklerini düşündüm. AutoCloseablejava 7'den önce yoktu değil mi?
Neil

31

Java 7 Önce , oldu hiçbir Java böyle özelliği (Java 7 ve üstü için bkz Asaph cevabını ilişkin ARM ).

Bunu elle yapmanız gerekiyordu ve bu bir acıdı :

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

Ve bu, istisnai durumların ne olduğu ne // Great codede hooray.close()atılamayacağı bir koddur .

Eğer varsa gerçekten sadece bir değişkenin kapsamını sınırlamak istiyorsunuz, o zaman basit bir kod bloğu işi yapar:

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

Ama muhtemelen kastettiğin bu değil.


1
// Great codeBir istisna atarsa Java eşdeğeriniz sorun olmamalıdır .
Cheeso

3
Yapıcı bir istisna attığında, kodunuzun orijinal istisnayı maskeleyen bir NullPointerException ile sonuçlanacağını düşünüyorum.
Michael Borgwardt

@Michael: aslında benim örneğim derlenmez, çünkü horrayo noktada başlatılmamış olabilir (şimdi düzeltildi).
Joachim Sauer

4
Yüzen basit blokların kapsamı sınırlandırabilmesi için +1. Ancak, bunları ne zaman görsem, neredeyse her zaman yöntemin daha küçük parçalara bölünmesi gerektiğinin bir göstergesi.
Mark Peters

1
yapıcıdan herhangi bir istisna yakalamak istiyorsanız, bunu try bloğunun içinde bulundurmalısınız. her şeyi başka bir deneme / yakalamaya sarmak zahmetli olurdu.
ths



8

En yakın java eşdeğeri

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



2

Kaynak yönetimiyle ilgileniyorsanız, Project Lombok@Cleanup ek açıklamayı sunar . Doğrudan kendi sitelerinden alınmıştır:

@CleanupKod yürütme yolu geçerli kapsamınızdan çıkmadan önce belirli bir kaynağın otomatik olarak temizlenmesini sağlamak için kullanabilirsiniz . Bunu, herhangi bir yerel değişken bildirimine aşağıdaki @Cleanup gibi ek açıklama ekleyerek yaparsınız :

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

Sonuç olarak, içinde bulunduğunuz kapsamın sonunda in.close()çağrılır. Bu çağrının bir dene / nihayet inşası yoluyla çalıştırılması garanti edilir. Bunun nasıl çalıştığını görmek için aşağıdaki örneğe bakın.

Temizlemek istediğiniz nesne türünün bir close() yöntemi yoksa , ancak başka bir bağımsız değişken içermeyen yöntemi varsa, bu yöntemin adını şu şekilde belirtebilirsiniz:

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

Varsayılan olarak, temizleme yönteminin olduğu varsayılır close(). Bağımsız değişken alan bir temizleme yöntemi aracılığıyla çağrılamaz @Cleanup.

Vanilya Java

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();
    }
  }
}

Lombok ile

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

Lütfen bu Java Anahtar Kelimeleri Listesine bakın .

  1. usingAnahtar kelime maalesef listenin parçası değildir.
  2. Ayrıca usingJava'da şimdilik olduğu gibi C # anahtar kelimesinin başka herhangi bir anahtar kelime ile eşdeğerliği de yoktur .

Bu tür "using"davranışları taklit try...catch...finallyetmek için, içindeki kaynakları elden çıkaracağınız bir blok kullanmanız gerekecektir finally.


6
Bunun usingbir anahtar kelime olmaması bir şey ifade etmez. Aynı özellik, @BalusC'nin de belirttiği gibi başka bir anahtar kelime ile uygulanabilir (ve uygulanacaktır!).
Joachim Sauer

1
Katılıyorum! Ama şimdilik yok, değil mi? Şu anda benzer bir şey olup olmadığını OP'nin sorduğu buydu. Gelecekteki sürümlerde var olacağını bilmek güzel, ancak bu şimdilik bir şeyi değiştirmiyor, öyle ya da böyle. Yine de @BalusC tarafından sağlanan bilgiler harika! =)
Will Marcouiller

2
Buna katılıyorum, ancak gönderiniz using, Java anahtar kelime listesinde olmaması, bu özelliğin Java dilinde olmadığı anlamına geldiğini söylüyor. Ve bu doğru değil.
Joachim Sauer

Yazımın söylediği şey buysa, niyetimi yansıtmak için düzenleme yapacağım.
Will Marcouiller

Cevabımı, usinganahtar kelime olmadığını ve şimdilik eşdeğer olmadığını belirterek düzenledim . Teşekkürler @ Joachim Sauer! =)
Will Marcouiller


0

Değişkenleri otomatik olarak kapatmak / elden çıkarmak yerine, bir değişkenin kapsamını sınırlandırmakla ilgili soruyu cevaplamak.

Java'da küme parantezleri kullanarak kapalı, anonim kapsamlar tanımlayabilirsiniz. Son derece basit.

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

Değişken hoorayyalnızca bu kapsamda mevcuttur ve onun dışında değildir.

Bu, yalnızca geçici olan tekrar eden değişkenleriniz varsa yararlı olabilir.

Örneğin, her biri dizine sahip. itemDeğişkenin for döngüsü üzerinde kapalı olması gibi (yani, sadece onun içinde mevcuttur), indexdeğişken de anonim kapsam üzerinden kapatılır.

// 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
    }
}

Bazen değişken kapsamı sağlamak için bir for döngüsünüz yoksa, ancak genel değişken adlarını kullanmak istiyorsanız bunu da kullanıyorum.

{
    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);
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.