2016-06-22 20 views
15

Bu, JDK'dan HashMap sınıfında keySet() yöntemi. Yazar neden alanı (keySet) yerel değişken ks'ye atadı?Yerel değişken için örnek alanı atama

public Set<K> keySet() { 
    Set<K> ks; 
    return (ks = keySet) == null ? (keySet = new KeySet()) : ks; 
} 

Yukarıdaki ve aşağıdaki arasındaki fark nedir? Bunun iplik güvenliği ile ilgisi var mı?

transient volatile Set<K> keySet; 

yerel değişken atama kullanarak sadece bir kez okuyarak, uçucu olduğundan şudur: abstract class AbstractMap<K,V> yılında keySet beyanında bakarsak olarak

public Set<K> keySet() { 
    return (keySet == null ? (keySet = new KeySet()) : keySet; 
} 
+0

Belki de; Yine de, değişkenin boş olmadığından ve bu değerin döndürülmesinden emin olunurken bir sınıf düzeyi değişkenini ayarlamaya çalışıyor gibi görünüyor. Bunun ötesinde bir ipucu yok. Bütün sınıfa bakmam gerek. –

+0

Muhtemelen niyetin netliği için – alphablue

+1

http://stackoverflow.com/q/28975415/3182664 http://stackoverflow.com/q/2785964/3182664 http://stackoverflow.com/q/ dosyasının kopyası olarak düşünülebilir. 37776179/3182664 http://stackoverflow.com/q/32619269/3182664 ve muhtemelen bazı diğerleri .... – Marco13

cevap

6

hafifçe genişletmek için (Set<K> ks yani) bir uçucu olmayan referans vs uçucu referans ile ilgili olacağını Michael'ın cevabı, keySet() yönteminin hiçbir zaman null değerini döndürmediğinden emin olmak için beklediğini ve performans avantajları sağladığına eminim. Bu kod Verilen

:

public Set<K> keySet() { 
    return (keySet == null ? (keySet = new KeySet()) : keySet; 
} 

O keySet alan ilk okuma (keySet == null) ve ikinci okuma, bunu arasındaki null ayarlı olabilir çok kanallı kod en azından teorik mümkün olacağını Geri döndü. Kodun geri kalanına bakmadım, ancak keySet'un potansiyel olarak null olarak atanabileceği başka yerler olduğunu varsayalım. Bunun, vahşi ya da savunmacı bir önlemde görülen bir sorunun sonucu olup olmadığı yazarlar için bir soru olacaktır.

gerçek kod: alanında sadece bir kere okunur olarak

public Set<K> keySet() { 
    Set<K> ks; 
    return (ks = keySet) == null ? (keySet = new KeySet()) : ks; 
} 

... Bu sorunu yoktur.

+0

Yup. Bu, çok iş parçacıklı bir ortamda güvenli olmakla ilgilidir. –

+0

@msandiford zorunlu olarak bir yerde null olarak ayarlanmamışsa, paylaşılan değişkenin iki küstah okuması olduğundan operasyonlar tekrar sipariş edilebilir. – Eugene

8

, bunu tanımlandığını göreceksiniz sağladığınız diğer örnekte olduğu gibi iki kez okumaktan daha ucuz. doğrudan keySet değişkeni dönmek olsaydı

Dahası, o zaman tüm istemci kodu

+2

Uçucu alan okuma hakkında cevap için teşekkürler, ben hakkında düşünmedim. "Uçucu olmayan bir referansa karşı uçucu bir referansla uğraşmak" bölümünü açıklayabilir misiniz? – joohwan

+1

"Uçucu olmayan referansa karşı uçucu bir referans" gibi bir kavram yoktur. – Boann

+0

@Boann Doğru. Teşekkürler. –