SORU
29 Mayıs 2009, Cuma


Java " verimliliği;Çift Başlatma" Ayracı;?

Hidden Features of Java en iyi cevap Double Brace Initialization bahsederçoksözdizimi cazip:

Set<String> flavors = new HashSet<String>() {{
    add("vanilla");
    add("strawberry");
    add("chocolate");
    add("butter pecan");
}};

Bu deyim sadece örnek bir başlatıcı ile anonim iç sınıf oluşturan "kullanabilirsiniz herhangi bir [...] içeren kapsam yöntemleri".

Asıl soru: bu kadarverimsizgöründüğü gibi mi? Kullanımı tek başlatmaları için sınırlı olmalıdır? (Ve tabii ki gösteriş!)

İkinci soru: yeni HashSet "bu" örnek başlatıcı ... herkes mekanizmasına ışık tutabilir? kullanılan olmalıdır

Üçüncü soru: bu çok deyim Vardırbelirsizüretiminde kullanmak için kodu?

Özet:Çok güzel cevaplar, teşekkürler herkese. Soru (3), insanlar sözdizimi net özellikle eğer kodunuzu bu aşina olmayabilir geliştiriciler için geçecek eğer arada bir yorum öneririm (gerçi) olması gerektiğini hissettim.

Soru (1), üretilen kod hızlı bir şekilde çalışması gerekir. Ekstra .sınıf dosyaları jar dosyası neden dağınıklığı ve programı başlangıçta biraz (@ölçmek için coobird sayesinde) yavaş. @Thilo işaret çöp toplama etkilenebilir, ve ekstra yüklenen sınıflar için bellek maliyeti bazı durumlarda bir faktör olabilir.

Soru (2) benim için çok ilginç oldu. Anlarım cevapları, ne var ne mekanda çalışan bu anonim iç sınıf uzanır sınıf nesnesi olma inşa ederek yeni operatör, ve bu nedenle bir "bu" değeri referans örnek olmak inşa edilmiştir. Çok temiz.

Genel olarak, mekanda çalışan entelektüel bir merak olarak beni vurur. Coobird ve diğer Diziler ile aynı etkiyi elde edebilirsiniz.asList, varargs yöntemleri, Google Koleksiyonları ve önerilen Java 7 Koleksiyonu hazır. Scala, JRuby, Groovy gibi JVM yeni diller de liste inşaatı için kısa notlar sunmak, ve Java ile birlikte. Mekanda çalışan sınıf clutters kadar, sınıf yükleme biraz yavaşlar ve kodu biraz daha belirsiz hale getirir göz önüne alındığında, muhtemelen ondan utangaç olurum. Ancak, sadece onun DENEMEDE oldu ve Java semantiği hakkında iyi huylu mızrak dövüşü, şölen seven bir arkadaşım, bu baharda yapmayı planlıyorum! ;-) Herkese teşekkürler!

CEVAP
29 Mayıs 2009, Cuma


İşte anonim iç sınıflar ile çok oyalandım zaman sorun:

2009/05/27  16:35             1,602 DemoApp2$1.class
2009/05/27  16:35             1,976 DemoApp2$10.class
2009/05/27  16:35             1,919 DemoApp2$11.class
2009/05/27  16:35             2,404 DemoApp2$12.class
2009/05/27  16:35             1,197 DemoApp2$13.class

/* snip */

2009/05/27  16:35             1,953 DemoApp2$30.class
2009/05/27  16:35             1,910 DemoApp2$31.class
2009/05/27  16:35             2,007 DemoApp2$32.class
2009/05/27  16:35               926 DemoApp2$33$1$1.class
2009/05/27  16:35             4,104 DemoApp2$33$1.class
2009/05/27  16:35             2,849 DemoApp2$33.class
2009/05/27  16:35               926 DemoApp2$34$1$1.class
2009/05/27  16:35             4,234 DemoApp2$34$1.class
2009/05/27  16:35             2,849 DemoApp2$34.class

/* snip */

2009/05/27  16:35               614 DemoApp2$40.class
2009/05/27  16:35             2,344 DemoApp2$5.class
2009/05/27  16:35             1,551 DemoApp2$6.class
2009/05/27  16:35             1,604 DemoApp2$7.class
2009/05/27  16:35             1,809 DemoApp2$8.class
2009/05/27  16:35             2,022 DemoApp2$9.class

Bu basit bir uygulama yapıyordum ve her sınıf derleneceği -- anonim iç sınıflar bol miktarda kullanılan class ayrı bir dosya içine ne zaman oluşturulan tüm sınıflar.

"Çift ayracı başlatma" olarak bahsedildiği, bir anonim iç sınıf bir örneğini başlatma engelleme, başka bir deyişle, yeni bir sınıf yarattığı için, her bir "başlatma", her ne amaçla genellikle yapmak bir tek nesne.

Java Sanal Makinesi onları kullanırken tüm bu dersleri okumak zorunda olduğunu belirterek, bir süre için bytecode verfication süreç ve bu gibi açabilir. class tüm bu dosyaları saklamak için gerekli disk alanı artışı söz değil.

Eğer çift ayracı başlatma, muhtemelen de denize gitmek pek iyi bir fikir değil gibi masraflarım yok gibi görünüyor. Ama Eddie açıklamalarda da belirttiği gibi, olası etkilerinin kesin olarak emin olmak için değil.


Sadece referans için, çift ayracı başlatma şudur:

List<String> list = new ArrayList<String>() {{
    add("Hello");
    add("World!");
}};

Bir "" Java özelliği, ama sadece yeniden: . Gizli gibi görünüyor

List<String> list = new ArrayList<String>() {

    // Instance initialization block
    {
        add("Hello");
        add("World!");
    }
};

anonymous inner class bir parçası olan instance initialization block temelde bir şey.


Joshua Bloch Project Coin çizgisinde oldu Collection Literals proposal

List<Integer> intList = [1, 2, 3, 4];

Set<String> strSet = {"Apple", "Banana", "Cactus"};

Map<String, Integer> truthMap = { "answer" : 42 };

Ne yazık ki, 41 ** Java 7 ne de 8 ve süresiz olarak rafa kaldırdı.


Deney

İşte basit bir deney yaptım test -- 1000 ArrayLists ile öğeleri "Hello" "World!" eklendi onları üzerinden add yöntemi kullanarak iki yöntem:

Yöntem 1: Çift Ayracı Başlatma

List<String> l = new ArrayList<String>() {{
  add("Hello");
  add("World!");
}};

Yöntem 2: Oluşturmak ArrayList add

List<String> l = new ArrayList<String>();
l.add("Hello");
l.add("World!");

1000 başlatmaları iki yöntemi kullanarak gerçekleştirmek için Java kaynak dosyası yazmak için basit bir program yaptım:

Test 1:

class Test1 {
  public static void main(String[] s) {
    long st = System.currentTimeMillis();

    List<String> l0 = new ArrayList<String>() {{
      add("Hello");
      add("World!");
    }};

    List<String> l1 = new ArrayList<String>() {{
      add("Hello");
      add("World!");
    }};

    /* snip */

    List<String> l999 = new ArrayList<String>() {{
      add("Hello");
      add("World!");
    }};

    System.out.println(System.currentTimeMillis() - st);
  }
}

Test 2:

class Test2 {
  public static void main(String[] s) {
    long st = System.currentTimeMillis();

    List<String> l0 = new ArrayList<String>();
    l0.add("Hello");
    l0.add("World!");

    List<String> l1 = new ArrayList<String>();
    l1.add("Hello");
    l1.add("World!");

    /* snip */

    List<String> l999 = new ArrayList<String>();
    l999.add("Hello");
    l999.add("World!");

    System.out.println(System.currentTimeMillis() - st);
  }
}

Lütfen unutmayın, bu geçen süreyi başlatmak için 1000 ArrayLists ve 1000 anonim iç sınıflar uzanan ArrayList kontrol kullanarak System.currentTimeMillis zamanlayıcı olmayan bir çok yüksek çözünürlük. Benim pencere sistemi, çözünürlüğü 15-16 milisaniye civarında.

Sonuçlar iki test 10 çalışan için şunlardı:

Test1 Times (ms)           Test2 Times (ms)
----------------           ----------------
           187                          0
           203                          0
           203                          0
           188                          0
           188                          0
           187                          0
           203                          0
           188                          0
           188                          0
           203                          0

Görüldüğü gibi, çift ayracı başlatma etrafında 190 ms fark yürütme zamanı var.

Bu arada, ArrayList başlatma yürütme zamanı 0 ms olduğu ortaya çıktı. Elbette, zamanlayıcı çözünürlüğünü dikkate alınmalıdır, ama altında 15 ms saniye olması muhtemeldir.

Böylece, iki yöntemin uygulama süresi gözle görülür bir fark var gibi görünüyor. Aslında iki başlatma yöntemleri biraz yükü var gibi görünüyor.

Ve evet, .class 1000 dosyaları Test1 çift ayracı başlatma test programı derleme tarafından oluşturulan vardı.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • DJAndrewRyan

    DJAndrewRyan

    22 Ocak 2007
  • RealPapaPit

    RealPapaPit

    16 Mart 2009
  • TouchePro

    TouchePro

    27 EYLÜL 2007