Java'da referans ile parametreleri iletebilir miyim?


Yanıtlar:


225

Java kafa karıştırıcıdır, çünkü her şey değerden geçer . Bununla birlikte , referans tipi bir parametre için (yani, ilkel tipte bir parametre değil), değerin içinden geçen referansın kendisidir , bu nedenle referansla geçer gibi görünür (ve insanlar genellikle bunun olduğunu iddia eder). Aşağıdakilerle gösterildiği gibi durum böyle değildir:

Object o = "Hello";
mutate(o)
System.out.println(o);

private void mutate(Object o) { o = "Goodbye"; } //NOT THE SAME o!

HelloKonsola yazdırır . Yazdırmaya yukarıdaki kodu istiyorsa seçenekleri Goodbyeşunlardır açık göndermede kullanmak şöyle:

AtomicReference<Object> ref = new AtomicReference<Object>("Hello");
mutate(ref);
System.out.println(ref.get()); //Goodbye!

private void mutate(AtomicReference<Object> ref) { ref.set("Goodbye"); }

48
Eğer gerçekten :) şaşırtmak insanlara isterseniz, ayrıca uzunluğu 1 dizisi referans oluşturmak için kullanılabilir
Christoffer

2
AtomicReference ve karşılık gelen sınıflar (AtomicInteger) bu tür işlemler için en iyisidir
Naveen

3
AtomicReference bir aşırı silahtır, orada bellek bariyeri istemezsiniz ve size mal olabilirler. JRuby, bir Nesne inşa ederken kullanılan değişken bir değişken nedeniyle performans problemi yaşamıştır. Diziyi geçici bir başvuru olarak kullanma seçeneği benim için yeterince iyi görünüyor ve birden fazla kez kullanıldığını gördüm.
Elazar Leibovich

Ben bu kafa karıştırıcı olduğunu düşünmüyorum, ancak bu normal bir davranıştır.Yığın üzerinde değer türleri var ve yığın üzerinde referans türleri var, ancak yığın üzerinde referans türleri için başvuru da var. Böylece her zaman yığında bulunan değerle çalışırsınız. Buradaki sorunun şu olduğuna inanıyorum: Yığında referans da yığını üzerinde başka bir değere işaret etmek mümkün mü? Ya da öbek üzerinde yaşayan bir değere işaret eden diğer referansın referansını mı geçeceksiniz?
eomeroff

Bu harika bir bilgi. diziler kullanıyordum ama bu iş için yapılmış bir şey gibi görünüyor. performans kritik bir döngü içinde ise, ancak bu vs dizilerin performansı hakkında bilmiyorum
steveh

65

Java'da referans ile parametreleri iletebilir miyim?

Hayır.

Neden ? Java'nın yöntemlere argüman iletmek için yalnızca bir modu vardır : değere göre.

Not:

İlkel için bunu anlamak kolaydır: değerin bir kopyasını alırsınız.

Tüm diğerleri için referansın bir kopyasını alırsınız ve buna değere göre geçiş de denir.

Hepsi bu resimde:

resim açıklamasını buraya girin


25

Java'da dil düzeyinde ref'ye benzer bir şey yoktur . Java'da sadece semantik değere göre geçiş vardır

Merak uğruna Java'da nesnelerinizi değiştirilebilir bir sınıfa sararak ref benzeri bir semantik uygulayabilirsiniz:

public class Ref<T> {

    private T value;

    public Ref(T value) {
        this.value = value;
    }

    public T get() {
        return value;
    }

    public void set(T anotherValue) {
        value = anotherValue;
    }

    @Override
    public String toString() {
        return value.toString();
    }

    @Override
    public boolean equals(Object obj) {
        return value.equals(obj);
    }

    @Override
    public int hashCode() {
        return value.hashCode();
    }
}

test durumu:

public void changeRef(Ref<String> ref) {
    ref.set("bbb");
}

// ...
Ref<String> ref = new Ref<String>("aaa");
changeRef(ref);
System.out.println(ref); // prints "bbb"

Bunun yerine neden java.lang.ref.Reference kullanmıyorsunuz?
Hardcoded

Referansın belirli bir yöntemi yok, değişken değil
dfa

neden kullanmıyorsunuz AtomicReference(ilkel olmayanlar için)? Veya AtomicSomething(örneğin AtomicBoolean:) ilkel için mi?
Arvin

Ne yazık ki, <T> ilkel türleri kabul etmiyor. Bunu yapmak istiyorum: Ref <int>
jk7

1
@ jk7 kullanmak zorunda gerçekten önemli yeterli mi intyerine Integer, boolyerine Booleanve benzeri? Yani, sarıcı sınıflar (sözdizimi için endişelenirseniz otomatik olarak açılır) çalışmaz mı?
Paul Stelian

18

"Java Programlama Dili" nde James Gosling'den:

"... Java'da tam olarak bir parametre geçirme modu var - değere göre geçiş - ve bu işleri basitleştirir."


2
Dil tanrısının ilanı cevap olarak ilan edilmelidir.
ingyhere

3
@ingyhere:: The pronouncement of the language god should be declared the answerPek değil. Java'nın yaratıcısının ne düşündüğüne veya inandığına rağmen, mutlak cevap dil ​​spesifikasyonundan bir alıntıdan gelir.
paercebal

1
Aslında bölüm 8.4.1'deki JLS'de ve JLS Gosling'e ilk yazar olarak atıfta bulunuyor: "Yöntem veya kurucu çağrıldığında (§15.12), gerçek bağımsız değişken ifadelerinin değerleri her biri yeni oluşturulan parametre değişkenlerini başlatır , yöntem veya kurucu gövdesinin yürütülmesinden önce bildirilen türde
ingyhere

Kesinlikle. Düşük temsilci üyelerinden alaycılık yardımcı olmaz.
duffymo

11

Yapabileceğini sanmıyorum. En iyi seçeneğiniz "ref tarafından" geçmek istediğiniz şeyi başka bir sınıf örneğine kapsüllemek ve (dış) sınıfın referansını (değere göre) geçirmek olabilir. Ne demek istediğimi anlarsan ...

yani yönteminiz, daha sonra arayan tarafından görülebilen iletilen nesnenin dahili durumunu değiştirir.


7

Java her zaman değere göre geçer.

Bir ilkel ilettiğinizde, değerin bir kopyasıdır, bir nesneyi ilettiğinizde referans işaretçisinin bir kopyasıdır.


4

Başka bir seçenek bir dizi kullanmaktır, örneğin; void method(SomeClass[] v) { v[0] = ...; } ancak 1) dizi, yöntem çağrılmadan önce başlatılmalıdır, 2) yine de örneğin takas yöntemini bu şekilde uygulayamaz ... Bu şekilde JDK, örn java.util.concurrent.atomic.AtomicMarkableReference.get(boolean[]).

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.