SORU
28 Temmuz 2012, CUMARTESİ


Dize Dize başvurular bir koleksiyon Nesnesi Havuz Veya Nesneleri topluluğudur

Corey McGlone, I İhbar hattına yazar tarafından javaranch sitedeki makaleyi okuduktan sonra kafam karıştı. Dizeleri, kelimenin tam Anlamıyla " adını verdi Kathy Sierra (co-founder of javaranch) and Bert Bates 6 Programcı OCP ve Java Rehberi.

Bay Corey ve Ms Kathy Sierra hakkında Dize Havuzu alıntı ne alıntı yapmaya çalışacağım.

1.Bay Corey göre McGlone :

  • Dize Dize Havuzu Nesneleri işaret eden kaynaklar topluluğudur.

  • String s = "Hello"; (Yığın adında bir nesne Yok Farz"") Merhaba, öbek üzerinde 22* *Dize bir nesne oluşturur ve Dize Havuzu (Sabit Tablo) bu nesne için bir referans olacaktır

  • String a = new String("Bye"); (Yığın üzerinde bir nesne Yok Farz", new operatör JVM Yığın. bir nesne yaratmak zorunda bırakacaktır "güle Güle" adlı

Şimdi bir Dize oluşturmak için "new" operatör açıklama ve referans kodu koyuyor ve ben bu yüzden bu yazıda biraz kafa karıştırıcı, -aşağıda makale kendisinden açıklama.

public class ImmutableStrings
{
    public static void main(String[] args)
    {
        String one = "someString";
        String two = new String("someString");

        System.out.println(one.equals(two));
        System.out.println(one == two);
    }
}

Bu durumda, biz aslında anahtar kelime "new." çünkü biraz farklı bir davranış ile sona Böyle bir durumda, iki Dize hazır başvurular hala sabit tabloya (String Literal Pool) koymak, ancak, JVM-zamanında yeni bir String nesnesi oluşturmak yükümlüdür anahtar "new," geldiğin zaman, sürekli masadan birini kullanmak yerine.

İşte diyagramı.. anlatılması

enter image description here

Bu yüzden, şu Dize Havuzu çok başvuru var bu Nesne anlamına mı geliyor ?

Burada Corey McGlone tarafından makaleye bağlantı

http://www.javaranch.com/journal/200409/Journal200409.jsp#a1

2.Sierra ve Bert Bates DENEMEDE bir kitap: Kathy göre

  • Java bellek daha verimli hale getirmek için, JVM bellek özel bir alan adında bir kenara "derleyici", Dize sabiti havuzu karşılaşmalar bir Dize, havuza benzer bir Dize çıkar zaten olup olmadığını görmek için denetler. Eğer bir oluşturur yeni bir Dize Nesne.

  • String s = "abc"; // bir Dize nesne ve değişken bir referans Oluşturur....

    cok iyi ama Şimdi aşağıda ifadesi biraz kafamı karıştırdı.

  • String s = new String("abc") // iki nesne ve değişken bir referans Oluşturur.

    Kitapta diyor ki,.... yeni bir Dize normal(non-havuz) bellekte nesne , ve" bakın... oysa "s ek bir harf "abc" havuzunda yer alacak.

    Kitapta yukarıdaki satırlar Corey McGlone tarafından yazı ile çakışır.

    • Eğer Dize Havuzu Corey McGlone tarafından belirtildiği gibi String nesne için başvurular topluluğu ise, nasıl oluyor o zaman yazınsal nesne "abc" kitabında bahsedildiği gibi havuzda yer olacak.

    • Nereye ve ne zaman bu Dize Havuzu bulunur.

Bir kod yazarken çok fazla bir önemi olmayacak olsa da, bu açık şüphe lütfen, ama bellek yönetimi açısından çok önemli. bu nedenle bu funda temizlemek için istiyorum.

CEVAP
28 Temmuz 2012, CUMARTESİ


Burada anlaşılması gereken önemli nokta String Java nesne ve içeriği - char[] private value field altında arasında ayrım olduğunu düşünüyorum. String temelde char[] dizi etrafında sarıcı, şifrelenmiş ve imkansız String sabit kalır, böylece değiştirmek için yapıyor. Ayrıca String sınıf aslında kullanılan hatırlar (aşağıya bakınız). Bu String iki farklı nesne (çok) basit aynı char[] işaret olabilir anlamına gelir.

Size birkaç örnek, char[] value alan (ararım . iç String hashCode() her hashCode() ile birlikte göstereceğim ^em>metindize ayırmak). Sonunda javap -c -verbose çıktı, birlikte test sınıfım için sürekli bir havuz ile göstereceğim. Lütfen sabit havuzu dize ile sınıf edebi havuzu karıştırmayın. Eskisi gibi değiller. Ayrıca Understanding javap's output for the Constant Pool bkz.

Önkoşullar

Test amaçlı String saklama sonları bu tür yardımcı bir yöntem oluşturdum:

private int showInternalCharArrayHashCode(String s) {
    final Field value = String.class.getDeclaredField("value");
    value.setAccessible(true);
    return value.get(s).hashCode();
}

char[] value bize özel String char[] aynı metin işaret olup olmadığını anlamaya yardımcı etkili hashCode() yazacaktır.

İki dize bir sınıfta hazır

Bu basit örnekten başlayalım.

Java kod

String one = "abc";
String two = "abc";

Eğer sadece "ab" "c" Java derleyici yazma BTW derleme zamanında birleştirme gerçekleştirir ve üretilen kod tamamen aynı olacak. Bu sadece tüm dizeleri derleme zamanında bilinen çalışır.

Sınıf sabit havuzu

Her sınıf kendi constant pool - eğer kaynak kodu birkaç kez oluştuğunda, yeniden kullanılabilecek sabit değerler listesi var. Dizeleri, sayılar, yöntem adları, vb ortak içerir.

İşte yukarıdaki örneğimizde sabit havuzunun içeriğini.

const #2 = String   #38;    //  abc
//...
const #38 = Asciz   abc;

Not için önemli şey bu dize gösteren String sabit nesne (#2) ve Unicode kodlanmış metin "abc" (#38) arasındaki ayrım.

Bayt kodu

Burada üretilen bayt kodu. one two başvurular hem #2 sabit "abc" dize: işaret ile atanır unutmayın

ldc #2; //String abc
astore_1    //one
ldc #2; //String abc
astore_2    //two

Çıktı

Her bir örnek için aşağıdaki değerleri basıyorum:

System.out.println(showInternalCharArrayHashCode(one));
System.out.println(showInternalCharArrayHashCode(two));
System.out.println(System.identityHashCode(one));
System.out.println(System.identityHashCode(two));

İki çift eşit olduğunu hiç sürpriz:

23583040
23583040
8918249
8918249

İki nesne char[] (aynı metin altında) equals() aynı testi için sadece geçmek anlamına gelir. Ama daha fazla, one two aynı başvurular. one == two için de geçerlidir. Belli ki one 71 *aynı nesneye işaret sonra one.value two.value eşit olmalıdır.

Edebi ve new String()

Java kod

Şimdi hepimiz bekledik bu örnek, bir dize ve String yeni kullanarak aynı değişmez. Bu iş nasıl olacak?

String one = "abc";
String two = new String("abc");

"abc" sabit kaynak kodu iki kez kullanılan aslında biraz ipucu ver

Sınıf sabit havuzu

Yukarıdaki gibi.

Bayt kodu

ldc #2; //String abc
astore_1    //one

new #3; //class java/lang/String
dup
ldc #2; //String abc
invokespecial   #4; //Method java/lang/String."<init>":(Ljava/lang/String;)V
astore_2    //two

Dikkatle bak! İlk nesne üstünde aynı şekilde, sürpriz oluşturulur. Sadece sabit bir referans zaten sürekli havuzu String (#2) oluşturulan alır. Ancak ikinci normal nesne oluşturucu çağrısı ile oluşturulur. Ama! String ilk bağımsız değişken olarak geçirilir. Bu decompiled olabilir:

String two = new String(one);

Çıktı

Çıkış biraz şaşırtıcı. İkinci çift, temsil başvuruları String nesne anlaşılır - biz yarattık iki String nesneleri - için yaratılan bizi sürekli havuz ve ikincisi oluşturuldu elle two. Ama, Dünyadaki ilk çift String iki nesne için öneriyor char[] value aynı dizi mi?!

41771
41771
8388097
16585653

String(String) constructor works nasıl baktığınız zaman açık (büyük ölçüde burada basitleştirilmiş) hale geliyor

public String(String original) {
    this.offset = original.offset;
    this.count = original.count;
    this.value = original.value;
}

Gördün mü? String yeni bir nesne var temel oluştururken, buyeniden kullanırchar[] value. Strings değişmez, asla değiştirilmiş olan veri yapısına kopyalamak için gerek yoktur.

String iki nesne varsa bile, hala aynı içeriği işaret olabilir. bu sorunun ipucu olduğunu düşünüyorum: Ve String nesne gördüğünüz gibi oldukça küçük kendisidir.

Değişiklik zamanı ve intern()

Java kod

Hadi başlangıçta iki farklı dizeleri kullandığını söylüyorlar ama bazı değişiklikler sonra hepsi aynı:

String one = "abc";
String two = "?abc".substring(1);  //also two = "abc"

Java derleyici (en azından benim) derleme zamanında bu işlemi gerçekleştirmek için yeterince zeki, bir bak

Sınıf sabit havuzu

Aniden, iki sabit dizeleri iki farklı sabit metin işaret ile sona erdi:

const #2 = String   #44;    //  abc
const #3 = String   #45;    //  ?abc
const #44 = Asciz   abc;
const #45 = Asciz   ?abc;

Bayt kodu

ldc #2; //String abc
astore_1    //one

ldc #3; //String ?abc
iconst_1
invokevirtual   #4; //Method String.substring:(I)Ljava/lang/String;
astore_2    //two

İlk dize her zamanki gibi inşa edilmiştir. İkinci ilk "?abc" sabit dize yükleme ve *101 arama* tarafından oluşturulur.

Çıktı

Burada sürpriz iki farklı dizeleri, bellek char[] iki farklı metin işaret var:

27379847
7615385
8388097
16585653

Peki, bu metinler gerçekten değilfarklı, equals() yöntem hala true verecektir. Aynı metnin iki gereksiz kopyaları var.

Şimdi iki egzersizleri koşmalıyız. İlk olarak, çalıştırmayı deneyin:

two = two.intern();

hash kodları yazdırmadan önce. one 108* noktası aynı metin için de değil sadece, ama aynı referans!

11108810
11108810
15184449
15184449

Bu one.equals(two) one == two iki testi geçecek demektir. Ayrıca "abc" metin sadece bir kez bellek (ikinci kopya çöp toplanacak) görünür, çünkü bazı hafıza kurtardık.

İkinci egzersiz biraz farklı, şuna bir bak

String one = "abc";
String two = "abc".substring(1);

Belli ki one two iki farklı nesne, iki farklı metin işaret ediyor. Ama nasıl çıktı char[] aynı diziye iki nokta gösteriyor?!?

23583040
23583040
11108810
8918249

Sana cevap bırakıyorum. substring() nasıl çalıştığını, böyle bir yaklaşımın avantajları ve 124* *o zaman sana öğretir.

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

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Cole Rolland

    Cole Rolland

    23 Kasım 2008
  • How Things Are Made

    How Things A

    17 HAZİRAN 2008
  • TantalizingTrance

    TantalizingT

    15 ŞUBAT 2009