Java membingungkan karena semuanya dilewatkan oleh nilai . Namun untuk parameter tipe referensi (yaitu bukan parameter tipe primitif) itu adalah referensi itu sendiri yang dilewatkan oleh nilai, maka itu tampaknya menjadi pass-by-reference (dan orang sering mengklaim bahwa itu adalah). Ini tidak terjadi, seperti yang ditunjukkan oleh hal berikut:
Object o ="Hello";
mutate(o)System.out.println(o);privatevoid mutate(Object o){ o ="Goodbye";}//NOT THE SAME o!
Akan mencetak Helloke konsol. Opsi jika Anda ingin mencetak kode di atas Goodbyeadalah dengan menggunakan referensi eksplisit sebagai berikut:
Juga, sebuah array dengan panjang 1 dapat digunakan untuk membuat referensi jika Anda benar-benar ingin membingungkan orang :)
Christoffer
2
AtomicReference dan kelas terkait (AtomicInteger) adalah yang terbaik untuk operasi seperti itu
Naveen
3
AtomicReference adalah kerja keras, Anda tidak perlu penghalang memori di sana, dan mereka mungkin dikenakan biaya. JRuby memiliki masalah kinerja karena variabel volatil yang digunakan ketika membangun Obyek. Opsi menggunakan array sebagai referensi ad-hoc tampaknya cukup baik untuk saya, dan saya telah melihatnya menggunakan lebih dari sekali.
Elazar Leibovich
Saya tidak berpikir bahwa ini membingungkan, namun ini adalah perilaku normal. Jenis nilai ada di stack dan tipe referensi ada di heap, tetapi referensi untuk tipe referensi ada di stack juga. Dengan demikian Anda selalu beroperasi dengan nilai yang ada di stack. Saya percaya bahwa pertanyaan di sini adalah: Apakah mungkin untuk melewati referensi dari stack yang menunjuk pada beberapa nilai lain yang juga ada di stack. Atau lulus referensi dari referensi lain yang menunjuk pada beberapa nilai yang hidup di heap?
eomeroff
ini saya info bagus. Saya telah menggunakan array tetapi ini sepertinya sesuatu yang dibangun untuk pekerjaan itu. saya tidak tahu tentang kinerja array vs ini, jika dalam loop kinerja kritis
steveh
65
Bisakah saya melewati parameter dengan referensi di Java?
Tidak.
Mengapa Java hanya memiliki satu mode meneruskan argumen ke metode: dengan nilai.
catatan:
Untuk primitif ini mudah dimengerti: Anda mendapatkan salinan nilainya.
Untuk semua yang lain Anda mendapatkan salinan referensi dan ini disebut juga lewat nilai.
Mengapa tidak menggunakan java.lang.ref.Referensi sebagai gantinya?
Hardcoded
java.lang.ref.Reference tidak memiliki metode set, tidak bisa berubah
DFA
mengapa tidak menggunakan AtomicReference(untuk non-primitif)? Atau AtomicSomething(misalnya AtomicBoolean:) untuk primitif?
Arvin
Sayangnya, <T> tidak menerima tipe primitif. Ingin melakukan ini: Ref <int>
jk7
1
@ jk7 Apakah benar-benar cukup penting untuk harus menggunakan intalih- alih Integer, boolbukannya Booleandan seterusnya? Yaitu, kelas wrapper (yang secara otomatis tidak terbuka jika Anda khawatir tentang sintaks) tidak berfungsi?
Paul Stelian
18
Dari James Gosling dalam "Bahasa Pemrograman Java":
"... Hanya ada satu mode passing parameter di Jawa - lulus dengan nilai - dan itu membuat semuanya menjadi sederhana ..."
Pernyataan dewa bahasa harus dinyatakan sebagai jawabannya.
ingyhere
3
@ingyhere:: The pronouncement of the language god should be declared the answerTidak juga. Terlepas dari apa yang dipikirkan atau diyakini oleh pencipta Jawa, jawaban absolut akan datang dari kutipan dari spesifikasi bahasa.
paercebal
1
Sebenarnya itu ada di JLS, di bagian 8.4.1 , dan JLS mengutip Gosling sebagai penulis pertama: "Ketika metode atau konstruktor dipanggil (§15.12), nilai-nilai dari argumen aktual ekspresi menginisialisasi variabel parameter yang baru dibuat , masing-masing dari tipe yang dideklarasikan, sebelum eksekusi tubuh metode atau konstruktor. "
ingyhere
Persis. Sarkasme dari anggota perwakilan rendah tidak membantu.
duffymo
11
Saya pikir kamu tidak bisa. Pilihan terbaik Anda mungkin untuk merangkum hal yang ingin Anda sampaikan "dengan ref" ke instance kelas lain, dan meneruskan referensi kelas (luar) (berdasarkan nilai). Jika Anda melihat apa yang saya maksud ...
yaitu metode Anda mengubah keadaan internal objek yang dilewati, yang kemudian terlihat oleh pemanggil.
Opsi lain adalah menggunakan array, mis.
void method(SomeClass[] v) { v[0] = ...; }
Tetapi 1) array harus diinisialisasi sebelum metode dipanggil, 2) masih ada yang tidak dapat mengimplementasikan mis. Metode swap dengan cara ini ... Cara ini digunakan di JDK, misalnya dalam java.util.concurrent.atomic.AtomicMarkableReference.get(boolean[]).
Jawaban:
Java membingungkan karena semuanya dilewatkan oleh nilai . Namun untuk parameter tipe referensi (yaitu bukan parameter tipe primitif) itu adalah referensi itu sendiri yang dilewatkan oleh nilai, maka itu tampaknya menjadi pass-by-reference (dan orang sering mengklaim bahwa itu adalah). Ini tidak terjadi, seperti yang ditunjukkan oleh hal berikut:
Akan mencetak
Hello
ke konsol. Opsi jika Anda ingin mencetak kode di atasGoodbye
adalah dengan menggunakan referensi eksplisit sebagai berikut:sumber
Tidak.
Mengapa Java hanya memiliki satu mode meneruskan argumen ke metode: dengan nilai.
catatan:
Untuk primitif ini mudah dimengerti: Anda mendapatkan salinan nilainya.
Untuk semua yang lain Anda mendapatkan salinan referensi dan ini disebut juga lewat nilai.
Semuanya ada dalam gambar ini:
sumber
Di Jawa tidak ada pada tingkat bahasa yang mirip dengan ref . Di Jawa hanya ada yang lewat nilai semantik
Demi rasa ingin tahu Anda dapat menerapkan semantik seperti-ref di Jawa hanya membungkus objek Anda dalam kelas yang bisa berubah:
Kasus cobaan:
sumber
AtomicReference
(untuk non-primitif)? AtauAtomicSomething
(misalnyaAtomicBoolean
:) untuk primitif?int
alih- alihInteger
,bool
bukannyaBoolean
dan seterusnya? Yaitu, kelas wrapper (yang secara otomatis tidak terbuka jika Anda khawatir tentang sintaks) tidak berfungsi?Dari James Gosling dalam "Bahasa Pemrograman Java":
sumber
The pronouncement of the language god should be declared the answer
Tidak juga. Terlepas dari apa yang dipikirkan atau diyakini oleh pencipta Jawa, jawaban absolut akan datang dari kutipan dari spesifikasi bahasa.Saya pikir kamu tidak bisa. Pilihan terbaik Anda mungkin untuk merangkum hal yang ingin Anda sampaikan "dengan ref" ke instance kelas lain, dan meneruskan referensi kelas (luar) (berdasarkan nilai). Jika Anda melihat apa yang saya maksud ...
yaitu metode Anda mengubah keadaan internal objek yang dilewati, yang kemudian terlihat oleh pemanggil.
sumber
Java selalu melewati nilai.
Ketika Anda melewati primitif itu adalah salinan nilai, ketika Anda melewati objek itu adalah salinan dari pointer referensi.
sumber
Opsi lain adalah menggunakan array, mis.
void method(SomeClass[] v) { v[0] = ...; }
Tetapi 1) array harus diinisialisasi sebelum metode dipanggil, 2) masih ada yang tidak dapat mengimplementasikan mis. Metode swap dengan cara ini ... Cara ini digunakan di JDK, misalnya dalamjava.util.concurrent.atomic.AtomicMarkableReference.get(boolean[])
.sumber