Bisakah "ini" menjadi nol di Java?

109

Melihat baris ini dalam metode kelas dan reaksi pertama saya adalah mengejek pengembang yang menulisnya .. Tapi kemudian, saya pikir saya harus memastikan bahwa saya benar terlebih dahulu.

public void dataViewActivated(DataViewEvent e) {
    if (this != null)
        // Do some work
}

Akankah baris itu dievaluasi sebagai salah?

Bryce Fischer
sumber
104
Selalu diejek dulu dan pertanyakan nanti. Lebih mudah untuk meminta maaf daripada menangkap kembali kesempatan emas untuk menjatuhkan seseorang dalam kesibukan.
Joel Etherton
5
1 untuk istilah "kesibukan belerang".
Marty Pitt
13
Anda tahu apa yang lucu? Ini bisa terjadi di C # karena bug compiler!
Blindy
1
@Blindy akan memberikan +1 untuk contoh kode.
Nathan Feger
6
baik di C # itu bisa menjadi nol. Dalam beberapa kasus tepi. Saya memiliki dorongan yang sama: mengejek si pengisap tapi kemudian saya tenang. Lihat di sini: stackoverflow.com/questions/2464097/…
Andrei Rînea

Jawaban:

88

Tidak, itu tidak bisa. Jika Anda menggunakan this, maka Anda dalam contoh jadi thisbukan null.

JLS mengatakan:

Saat digunakan sebagai ekspresi utama, kata kunci this menunjukkan nilai yang merupakan referensi ke objek yang menggunakan metode instance (§15.12), atau ke objek yang sedang dibangun.

Jika Anda memanggil metode dari suatu objek, maka objek itu ada atau Anda akan memiliki NullPointerExceptionsebelumnya (atau itu metode statis tetapi kemudian, Anda tidak dapat menggunakannya thisdi dalamnya).


Sumber:

Colin Hebert
sumber
4
Saya tidak tahu secara mendalam tentang Java, tetapi dalam C ++ thismetode contoh bisa menjadi NULL. Jadi saya tidak begitu yakin ini adalah alasan yang cukup di Jawa.
kennytm
4
pengecualian pointer nol dalam sesuatu seperti foo.bar()akan dilemparkan ketika fooditemukan null. itu terjadi sebelum memasuki metode, tetapi kisah sebenarnya adalah tidak ada metode untuk mencoba memanggil.
Claudiu
5
@KennyTM: cukup di Java. Jika Anda menggunakan thiskata kunci dan dikompilasi, nilainya bukan nol saat Anda mengamatinya. Tetapi seperti yang dikatakan orang lain, hal itu tidak mencegah NPE saat mencoba memanggil metode, misalnya. Tapi itu benar-benar di luar kendali Anda sebagai metode dan pemeriksaan nol di dalam metode tidak akan mengubah apa pun.
Mark Peters
5
@Kenny: Bukan tanpa perilaku tidak terdefinisi , meskipun jika Anda mengetahui detail implementasi Anda, Anda dapat menggunakannya.
4
Saya tidak akan berlangganan jawaban pasti ini, bahkan jika itu masuk akal. Saya memiliki laporan kerusakan untuk aplikasi Android di mana ini == null ketika metode instance dipanggil tepat setelah variabel menjadi null-ified dari thread lain. Panggilan sebenarnya tetap berjalan meskipun variabelnya null, dan crash ketika mencoba membaca anggota instance :)
Adrian Crețu
63

Ini seperti bertanya pada diri sendiri, "Apakah saya hidup?" thistidak pernah bisa menjadi nol

bragboy
sumber
44
apakah saya hidup ?! Ya Tuhan, saya tidak tahu lagi
Claudiu
Anda membuatnya terdengar seperti this != nullbukti dengan sendirinya. Ini tidak - dalam C ++, misalnya, thismungkin NULL, untuk metode non-virtual.
Niki
1
@nikie Dalam beberapa hal, ini terbukti dengan sendirinya. Bahkan di C ++, program apa pun di mana ini terjadi memiliki perilaku yang tidak ditentukan. Ini juga dapat terjadi untuk fungsi virtual di GCC: ideone.com/W7RmU .
Johannes Schaub - litb
8
@ John: Anda. Bagian dari penyiksaan adalah Anda tidak dapat memastikannya.
@ JohannesSchaub-litb Tidak benar bahwa perilaku program c ++ dengan ref null untuk ini tidak ditentukan. Didefinisikan selama Anda tidak membedakan ini
Rune FS
9

Tidak pernah , kata kunci 'this' itu sendiri mewakili instance (objek) yang hidup saat ini dari kelas itu dalam lingkup kelas itu, yang dengannya Anda dapat mengakses semua bidang dan anggotanya (termasuk konstruktor) dan yang terlihat dari kelas induknya.

Dan, yang lebih menarik, coba atur:

this = null;

Pikirkan tentang itu? Bagaimana mungkin, bukankah itu seperti memotong dahan tempat Anda duduk. Karena kata kunci 'ini' tersedia dalam ruang lingkup kelas maka segera setelah Anda mengatakan ini = null; Di mana saja di dalam kelas maka pada dasarnya Anda meminta JVM untuk membebaskan memori yang ditugaskan ke objek itu di tengah-tengah beberapa operasi yang JVM tidak bisa membiarkannya terjadi karena ia perlu kembali dengan aman setelah menyelesaikan operasi itu.

Selain itu, mencoba this = null;akan menghasilkan kesalahan kompilator. Alasannya cukup sederhana, kata kunci di Java (atau bahasa apapun) tidak akan pernah bisa diberi nilai yaitu kata kunci tidak akan pernah bisa menjadi nilai kiri dari operasi penugasan.

Contoh lain, Anda tidak bisa mengatakan:

true = new Boolean(true);
true = false;
sactiw
sumber
Penjelasan yang bagus teman.
Pankaj Sharma
@PankajSharma Terima kasih :)
sactiw
Saya menemukan ini karena saya ingin melihat apakah saya dapat menggunakan this = null. Instance saya berada di android tempat saya ingin menghapus tampilan dan menyetel objek yang menangani tampilan ke null. Kemudian saya ingin menggunakan metode remove()yang akan menghapus tampilan aktual dan kemudian objek penangan akan dianggap tidak berguna, jadi saya ingin membatalkannya.
Yokich
Tidak yakin saya setuju dengan klaim Anda. (setidaknya bagian tengah; bagian lvalue baik-baik saja ... meskipun saya cukup yakin sebenarnya ada bahasa rusak yang memungkinkan Anda untuk menetapkan misalnya benar = salah (dan bahkan bahasa yang tidak saya sebut rusak mungkin mengizinkannya Refleksi atau tipu daya serupa)). Anyways, Jika saya memiliki beberapa objek foo dan saya harus melakukannya (mengabaikan bahwa itu ilegal) foo.this = null, foo masih akan menunjuk ke memori dan JVM tidak akan mengumpulkan sampah itu.
Foon
@Foon well, pertanyaannya persis berbicara tentang bahasa Java, terlebih lagi, saya belum menemukan bahasa apa pun di mana pengaturan this = null diizinkan. Artinya, jika memang ada bahasa seperti itu maka saya sangat meragukan bahwa 'ini' dalam bahasa seperti itu akan memiliki konteks dan ideologi yang sama.
mulai
7

Jika Anda mengkompilasi dengan -target 1.3atau sebelumnya, maka mungkin luar . Atau setidaknya dulu ...thisnull

Tom Hawtin - tackline
sumber
2
Saya kira melalui refleksi kita dapat mengatur bagian luar ini menjadi nol. bisa menjadi lelucon April bodoh pada seseorang ketika dia mendapat pengecualian pointer nol dalam referensiOuter.this.member
bereputasi
3

Tidak. Untuk memanggil metode instance kelas, instance tersebut harus ada. Instance ini secara implisit diteruskan sebagai parameter ke metode, direferensikan oleh this. Jika thisada nullmaka tidak akan ada contoh untuk memanggil metode.

Claudiu
sumber
3

Bahasa tidak cukup hanya memaksakannya. VM perlu memberlakukannya. Kecuali jika VM memberlakukannya, Anda dapat menulis kompiler yang tidak memberlakukan pemeriksaan null sebelum memanggil metode yang ditulis di Java. Opcode untuk pemanggilan metode instance termasuk memuat referensi ini ke tumpukan, lihat: http://java.sun.com/docs/books/jvms/second_edition/html/Compiling.doc.html#14787 . Mengganti ini untuk ref null memang akan menghasilkan tes yang salah

Rune FS
sumber
3

Dalam metode kelas statis, thistidak ditentukan karena thisdikaitkan dengan instance dan bukan kelas. Saya percaya ini akan memberikan kesalahan kompiler untuk mencoba menggunakan thiskata kunci dalam konteks statis.

burkestar.dll
sumber
2

Sebuah normal thistidak pernah bisa nulldalam kode Java 1 yang sebenarnya , dan contoh Anda menggunakan normal this. Lihat jawaban lainnya untuk lebih jelasnya.

Seorang yang memenuhi syarat this seharusnya tidak pernah null, tetapi mungkin untuk memecahkan ini. Pertimbangkan hal berikut:

public class Outer {
   public Outer() {}

   public class Inner {
       public Inner() {}

       public String toString() {
           return "outer is " + Outer.this;  // Qualified this!!
       }
   }
}

Saat kita ingin membuat sebuah instance Inner, kita perlu melakukan ini:

public static void main(String[] args) {
    Outer outer = new Outer();
    Inner inner = outer.new Inner();
    System.out.println(inner);

    outer = null;
    inner = outer.new Inner();  // FAIL ... throws an NPE
}

Outputnya adalah:

outer is Outer@2a139a55
Exception in thread "main" java.lang.NullPointerException
        at Outer.main(Outer.java:19)

menunjukkan bahwa upaya kami untuk membuat Innerdengan nullreferensi ke dalamnya Outertelah gagal.

Faktanya, jika Anda tetap berada di dalam amplop "Java Murni", Anda tidak dapat memecahkannya.

Namun, setiap Innerinstance memiliki finalbidang sintetis tersembunyi (disebut "this$0") yang berisi referensi ke Outer. Jika Anda benar-benar rumit, Anda dapat menggunakan cara "non-murni" untuk menetapkan nullke bidang.

  • Anda bisa menggunakan Unsafe untuk melakukannya.
  • Anda dapat menggunakan kode asli (misalnya JNI) untuk melakukannya.
  • Anda bisa melakukannya dengan menggunakan refleksi.

Apa pun cara Anda melakukannya, hasil akhirnya adalah Outer.thisekspresi akan bernilai null2 .

Singkatnya, itu adalah mungkin untuk memenuhi syarat thisuntuk menjadi null. Tetapi tidak mungkin jika program Anda mengikuti aturan "Pure Java".


1 - Saya mengabaikan trik seperti "menulis" bytecode dengan tangan dan meneruskannya sebagai Java asli, mengubah bytecode menggunakan BCEL atau yang serupa, atau melompat ke kode asli dan mengotak-atik register yang disimpan. IMO, itu BUKAN Java. Secara hipotesis, hal-hal seperti itu mungkin juga terjadi sebagai akibat dari bug JVM ... tapi saya tidak ingat setiap melihat laporan bug.

2 - Sebenarnya, JLS tidak mengatakan seperti apa perilakunya, dan bisa jadi tergantung pada implementasi ... antara lain.

Stephen C
sumber
1

Saat Anda memanggil metode dengan nullreferensi, NullPointerExceptionakan dibuang dari Java VM. Ini berdasarkan spesifikasi jadi jika VM Java Anda benar-benar sesuai dengan spesifikasi, thistidak akan pernah null.

tia
sumber
1

Jika metodenya statis, maka tidak ada this. Jika metode ini virtual, maka thistidak boleh nol, karena untuk memanggil metode tersebut, waktu proses perlu merujuk ke vtable menggunakan thispointer. Jika metodenya tidak virtual maka, ya, mungkin thisnihil.

C # dan C ++ mengizinkan metode non-virtual, tetapi di Java semua metode non-statis adalah virtual, jadi thistidak akan pernah null.

John Henckel
sumber
0

tl; dr, "ini" hanya dapat dipanggil dari metode non-statis dan kita semua tahu bahwa metode non-statis dipanggil dari beberapa jenis objek yang tidak boleh null.

Adam
sumber