Baca klarifikasi untuk kode berikut:
StringBuilder sample = new StringBuilder();
StringBuilder referToSample = sample;
referToSample.append("B");
System.out.println(sample);
Ini akan mencetak B
sehingga bukti sample
dan referToSample
objek mengacu pada referensi memori yang sama.
StringBuilder sample = new StringBuilder();
StringBuilder referToSample = sample;
sample.append("A");
referToSample.append("B");
System.out.println(referToSample);
Ini akan mencetak AB
yang juga membuktikan hal yang sama.
StringBuilder sample = new StringBuilder();
StringBuilder referToSample = sample;
referToSample = null;
referToSample.append("A");
System.out.println(sample);
Jelas ini akan melempar NullPointerException
karena saya mencoba memanggil append
referensi nol.
StringBuilder sample = new StringBuilder();
StringBuilder referToSample = sample;
referToSample = null;
sample.append("A");
System.out.println(sample);
Jadi inilah pertanyaan saya, mengapa sampel kode terakhir tidak dibuang NullPointerException
karena yang saya lihat dan pahami dari dua contoh pertama adalah jika dua objek merujuk ke objek yang sama maka jika kita mengubah nilai apa pun maka itu juga akan mencerminkan yang lain karena keduanya menunjuk ke referensi memori yang sama. Jadi mengapa aturan itu tidak berlaku di sini? Jika saya menetapkan null
ke referToSample maka sampel juga harus nol dan harus membuang NullPointerException tetapi tidak membuangnya, mengapa?
sumber
sample
masihsample
. Anda hanya berubahreferToSample
.sample
danreferToSample
sebagai objek tetapi mereka bukan objek, mereka adalah variabel. Variabel dapat menyimpan referensi ke suatu objek, tetapi itu sendiri bukanlah objek. Ini perbedaan yang halus, tetapi pada dasarnya itu adalah inti dari kebingungan Anda.volatile
,final
,=
,==
...) bila diterapkan variabel objek mempengaruhi pointer , bukan objek itu mengacu.Jawaban:
null
tugas tidak mengubah nilai dengan menghancurkan objek itu secara global. Perilaku semacam itu akan menyebabkan bug yang sulit dilacak dan perilaku yang berlawanan dengan intuisi. Mereka hanya merusak referensi khusus itu .Untuk kesederhanaan, katakanlah itu
sample
menunjuk ke alamat 12345. Ini mungkin bukan alamatnya, dan hanya digunakan untuk mempermudah di sini.Alamat biasanya diwakili dengan heksadesimal aneh yang diberikan1Object#hashCode()
, tetapi ini bergantung pada implementasi.StringBuilder sample = new StringBuilder(); //sample refers to //StringBuilder at 12345 StringBuilder referToSample = sample; //referToSample refers to //the same StringBuilder at 12345 //SEE DIAGRAM 1 referToSample = null; //referToSample NOW refers to 00000, //so accessing it will throw a NPE. //The other reference is not affected. //SEE DIAGRAM 2 sample.append("A"); //sample STILL refers to the same StringBuilder at 12345 System.out.println(sample);
Dari garis-garis yang di tandai
See diagram
diagram benda pada saat itu adalah sebagai berikut:Diagram 1:
[StringBuilder sample] -----------------> [java.lang.StringBuilder@00012345] ↑ [StringBuilder referToSample] ------------------------/
Diagram 2:
[StringBuilder sample] -----------------> [java.lang.StringBuilder@00012345] [StringBuilder referToSample] ---->> [null pointer]
Diagram 2 menunjukkan bahwa pembatalan
referToSample
tidak memutuskan referensi darisample
StringBuilder di00012345
.Pertimbangan 1 GC membuat ini tidak masuk akal.
sumber
hashCode()
adalah tidak sama dengan alamat memorihashCode
biasanya mendefinisikannya untuk mengembalikan nilai yang tidak ada hubungannya dengan alamat memori. Saya pikir Anda dapat membuat poin Anda tentang referensi objek vs. objek tanpa menyebutkanhashCode
. Poin-poin penting tentang bagaimana mendapatkan alamat memori dapat ditinggalkan untuk hari lain.Awalnya seperti yang Anda katakan
referToSample
merujuksample
seperti yang ditunjukkan di bawah ini:1. Skenario1:
2. Skenario1 (lanjutan):
Di sini seperti
referToSample
yang dimaksudsample
, jadi itu ditambahkan "B" saat Anda menulisreferToSample.append("B")
Hal yang sama terjadi di Scenario2:
Tapi, di 3. Scenario3: seperti kata hexafraction,
ketika Anda menetapkan
null
untukreferToSample
ketika itu mengacusample
tidak perubahan nilai bukan hanya melanggar referensi darisample
, dan sekarang itu menunjuk tempat . seperti yang ditunjukkan di bawah ini:Sekarang, sebagai tidak
referToSample
menunjukkan kemana-mana , jadi sementara AndareferToSample.append("A");
tidak akan memiliki nilai atau referensi di mana ia dapat menambahkan A. Jadi, itu akan dibuangNullPointerException
.TAPI
sample
masih sama seperti saat Anda menginisialisasiStringBuilder sample = new StringBuilder();
jadi sudah diinitalisasi, jadi sekarang bisa menambahkan A, dan tidak akan membuangNullPointerException
sumber
referToSample = sample;
Anda merujuk ke sampel, Anda hanya menyalin alamat dari apa yang direferensikanSingkatnya: Anda menetapkan null ke variabel referensi, bukan ke objek.
Dalam satu contoh, Anda mengubah status objek yang dirujuk oleh dua variabel referensi. Jika ini terjadi, kedua variabel referensi akan mencerminkan perubahan tersebut.
Dalam contoh lain, Anda mengubah referensi yang ditetapkan ke satu variabel, tetapi ini tidak berpengaruh pada objek itu sendiri, sehingga variabel kedua, yang masih merujuk ke objek asli, tidak akan melihat perubahan apa pun dalam status objek.
Untuk "aturan" spesifik Anda:
Sekali lagi, Anda mengacu pada mengubah status satu objek yang dirujuk kedua variabel .
Sekali lagi, Anda mengubah referensi satu variabel yang sama sekali tidak berpengaruh pada referensi variabel lainnya.
Ini adalah dua tindakan yang sangat berbeda dan akan menghasilkan dua hasil yang sangat berbeda.
sumber
Lihat diagram sederhana ini:
Ketika Anda memanggil metode pada
referToSample
, kemudian[your object]
diperbarui, sehingga mempengaruhisample
juga. Tetapi ketika Anda mengatakannyareferToSample = null
, maka Anda hanya mengubah apa yangreferToSample
dimaksud .sumber
Di sini 'sample' dan 'referToSample' mereferensikan objek yang sama. Itu adalah konsep pointer berbeda yang mengakses lokasi memori yang sama. Jadi menugaskan satu variabel referensi ke null tidak merusak objek.
referToSample = null;
berarti 'referToSample' hanya menunjuk ke nol, objek tetap sama dan variabel referensi lainnya berfungsi dengan baik. Jadi untuk 'sample' yang tidak menunjuk ke null dan memiliki objek yang valid
sample.append("A");
bekerja dengan baik. Tetapi jika kami mencoba menambahkan null ke 'referToSample', NullPointException akan ditampilkan. Itu adalah,
referToSample .append("A");-------> NullPointerException
Itulah mengapa Anda mendapatkan NullPointerException di cuplikan kode ketiga Anda.
sumber
Setiap kali kata kunci baru digunakan, itu Membuat Objek di Heap
1) Contoh StringBuilder = new StringBuilder ();
2) StringBuilder referToSample = sample;
Dalam 2) Referensi referSample dibuat pada sampel objek yang sama
jadi referToSample = null; adalah Nulling Only the referSample Reference tidak memberikan efek pada sampel, itulah sebabnya Anda tidak mendapatkan Pengecualian NULL Pointer Berkat Koleksi Sampah Java
sumber
Mudah saja, Java tidak memiliki referensi lewat, itu hanya melewati referensi objek.
sumber