Saya dapat melihat itu @Nullable
dan @Nonnull
penjelasan dapat membantu dalam mencegah NullPointerException
tetapi mereka tidak menyebar terlalu jauh.
- Keefektifan anotasi ini menurun sepenuhnya setelah satu tingkat tipuan, jadi jika Anda hanya menambahkan beberapa, mereka tidak menyebar terlalu jauh.
- Karena anotasi ini tidak ditegakkan dengan baik, ada bahaya menganggap nilai yang ditandai dengan
@Nonnull
tidak nol dan akibatnya tidak melakukan pemeriksaan nol.
Kode di bawah menyebabkan parameter yang ditandai dengan @Nonnull
menjadi null
tanpa menaikkan keluhan. Itu melempar NullPointerException
ketika dijalankan.
public class Clazz {
public static void main(String[] args){
Clazz clazz = new Clazz();
// this line raises a complaint with the IDE (IntelliJ 11)
clazz.directPathToA(null);
// this line does not
clazz.indirectPathToA(null);
}
public void indirectPathToA(Integer y){
directPathToA(y);
}
public void directPathToA(@Nonnull Integer x){
x.toString(); // do stuff to x
}
}
Apakah ada cara untuk membuat anotasi ini lebih ketat ditegakkan dan / atau disebarkan lebih lanjut?
java
annotations
nullpointerexception
nullable
code-standards
Mike Rylander
sumber
sumber
@Nullable
atau@Nonnull
, tetapi jika mereka layak itu sangat "kemungkinan untuk mengumpulkan debat"@Nonnull
ketika memanggil@Nonnull
metode dengan variabel nullable. Tentu saja, casting dengan anotasi tidak dimungkinkan di Java 7, tetapi Java 8 akan menambahkan kemampuan untuk menerapkan anotasi pada penggunaan variabel, termasuk gips. Jadi ini mungkin untuk diterapkan di Jawa 8.(@NonNull Integer) y
secara sintaksis mungkin, tetapi kompiler tidak diizinkan untuk memancarkan kode byte tertentu berdasarkan anotasi. Untuk pernyataan runtime, metode pembantu kecil sudah cukup seperti yang dibahas di bugs.eclipse.org/442103 (mis.,directPathToA(assertNonNull(y))
) - tetapi ingatlah, ini hanya membantu untuk gagal dengan cepat. Satu-satunya cara yang aman adalah dengan melakukan pemeriksaan nol yang sebenarnya (ditambah semoga implementasi alternatif di cabang lain).@Nonnull
dan yang@Nullable
Anda bicarakan, karena ada beberapa pengumuman serupa (Lihat pertanyaan ini ). Apakah Anda berbicara tentang anotasi dalam paketjavax.annotation
?Jawaban:
Jawaban singkat: Saya kira penjelasan ini hanya berguna bagi IDE Anda untuk memperingatkan Anda tentang kemungkinan kesalahan pointer nol.
Seperti yang dikatakan dalam buku "Kode Bersih", Anda harus memeriksa parameter metode publik Anda dan juga menghindari memeriksa invarian.
Tip lain yang baik adalah tidak pernah mengembalikan nilai null, tetapi menggunakan Pola Objek Null sebagai gantinya.
sumber
Optional
tipe alih-alih polosnull
Optional
dan nullable dalam kasus ini adalah bahwaOptional
lebih baik berkomunikasi bahwa nilai ini sengaja dapat kosong. Tentu saja, ini bukan tongkat ajaib dan dalam runtime itu mungkin gagal persis seperti variabel nullable. Namun, penerimaan API oleh programmer lebih baikOptional
menurut saya.Selain IDE Anda memberi Anda petunjuk ketika Anda meneruskan
null
ke metode yang mengharapkan argumen tidak menjadi nol, ada keuntungan lebih lanjut:Ini dapat membantu kode Anda lebih mudah dikelola (karena Anda tidak perlu
null
memeriksa) dan lebih sedikit kemungkinan kesalahan.sumber
assert
. Saya menemukan@Nullable
dan@Nonnull
menjadi ide yang berguna, tetapi saya ingin lebih banyak kekuatan di belakangnya, daripada kami berhipotesis tentang apa yang bisa dilakukan dengan mereka, yang masih membuka kemungkinan untuk tidak melakukan apa pun dengan mereka.Saya pikir pertanyaan awal ini secara tidak langsung menunjuk ke rekomendasi umum bahwa pemeriksaan null-pointer run-time masih diperlukan, meskipun @NonNull digunakan. Lihat tautan berikut:
Anotasi Tipe Java 8 yang baru
Di blog di atas, disarankan agar:
sumber
Mengompilasi contoh asli di Eclipse at compliance 1.8 dan dengan analisis nol berbasis anotasi diaktifkan, kami mendapatkan peringatan ini:
Peringatan ini dianalogikan dengan peringatan yang Anda dapatkan ketika mencampur kode yang dibuat dengan kode lama menggunakan tipe mentah ("konversi tidak dicentang"). Kami memiliki situasi yang sama persis di sini: metode
indirectPathToA()
memiliki tanda tangan "lawas" karena tidak menentukan kontrak nol. Alat-alat dapat dengan mudah melaporkan ini, sehingga mereka akan memburu Anda semua gang di mana anotasi nol perlu diperbanyak tetapi belum.Dan ketika menggunakan pintar
@NonNullByDefault
kita bahkan tidak harus mengatakan ini setiap saat.Dengan kata lain: apakah anotasi nol atau "menyebar sangat jauh" tergantung pada alat yang Anda gunakan, dan seberapa keras Anda memperhatikan semua peringatan yang dikeluarkan oleh alat tersebut. Dengan TYPE_USE null annotations Anda akhirnya memiliki opsi untuk membiarkan alat memperingatkan Anda tentang setiap NPE yang mungkin ada dalam program Anda, karena nullness telah menjadi properti intris dari sistem tipe.
sumber
Saya setuju bahwa anotasi "jangan menyebar terlalu jauh". Namun, saya melihat kesalahan di sisi programmer.
Saya mengerti
Nonnull
anotasi sebagai dokumentasi. Metode berikut ini menyatakan bahwa diperlukan (sebagai prasyarat) argumen non-nolx
.Cuplikan kode berikut ini kemudian berisi bug. Metode panggilan
directPathToA()
tanpa penegakan yangy
non-null (yaitu, itu tidak menjamin prasyarat dari metode yang disebut). Satu kemungkinan adalah menambahkanNonnull
anotasi juga keindirectPathToA()
(menyebarkan prakondisi). Kemungkinan kedua adalah untuk memeriksa nullityy
inindirectPathToA()
dan menghindari panggilandirectPathToA()
ketikay
null.sumber
@Nonnull
memilikiindirectPathToA(@Nonnull Integer y)
IMHO praktik yang buruk: Anda akan perlu untuk mainain propagasi pada panggilan tumpukan penuh (jadi jika Anda menambahkannull
cek didirectPathToA()
, Anda akan harus mengganti@Nonnull
dengan@Nullable
dalam panggilan tumpukan penuh). Ini akan menjadi upaya pemeliharaan besar untuk aplikasi besar.Apa yang saya lakukan dalam proyek saya adalah untuk mengaktifkan opsi berikut dalam inspeksi kode "Kondisi & pengecualian konstan":
Sarankan @ anotasi yang dapat dihapus untuk metode yang dapat mengembalikan nol dan melaporkan nilai yang dapat diupgrade yang dilewatkan ke parameter yang tidak dianotasi
Saat diaktifkan, semua parameter yang tidak dianotasi akan diperlakukan sebagai bukan nol dan karenanya Anda juga akan melihat peringatan pada panggilan tidak langsung Anda:
Untuk pemeriksaan yang lebih kuat, Kerangka Pemeriksa mungkin merupakan pilihan yang baik (lihat tutorial yang bagus ini .
Catatan : Saya belum menggunakannya dan mungkin ada masalah dengan kompiler Jack: lihat laporan bug ini
sumber
Di Jawa saya akan menggunakan jenis Opsional Guava . Menjadi tipe aktual Anda mendapatkan jaminan kompilator tentang penggunaannya. Sangat mudah untuk mem-bypassnya dan mendapatkan
NullPointerException
, tetapi setidaknya tanda tangan dari metode tersebut dengan jelas mengomunikasikan apa yang diharapkan sebagai argumen atau apa yang mungkin kembali.sumber
java.util.Optional
daripada kelas Guava. Lihat catatan / perbandingan Guava untuk perincian tentang perbedaan.Jika Anda menggunakan Kotlin, mendukung anotasi nullability ini di kompilernya dan akan mencegah Anda meneruskan null ke metode java yang memerlukan argumen non-nol. Meskipun pertanyaan ini awalnya ditargetkan di Jawa, saya menyebutkan fitur Kotlin ini karena secara khusus ditargetkan pada anotasi Java ini dan pertanyaannya adalah "Apakah ada cara untuk membuat anotasi ini lebih ketat ditegakkan dan / atau disebarkan lebih lanjut?" dan fitur ini membuat penjelasan ini lebih ketat .
Kelas Java menggunakan
@NotNull
anotasiKelas Kotlin memanggil kelas Java dan meneruskan null untuk argumen yang dijelaskan dengan @NotNull
Kesalahan kompilator Kotlin menegakkan
@NotNull
anotasi.lihat: http://kotlinlang.org/docs/reference/java-interop.html#nullability-annotations
sumber
myString.hashCode()
masih akan melempar NPE bahkan jika@NotNull
tidak ditambahkan dalam parameter. Jadi apa yang lebih spesifik tentang menambahkannya?Karena Java 8 fitur baru Opsional Anda tidak boleh menggunakan @Nullable atau @Notnull dalam kode Anda sendiri lagi . Ambil contoh di bawah ini:
Itu dapat ditulis ulang dengan:
Menggunakan opsional memaksa Anda untuk memeriksa nilai nol . Dalam kode di atas, Anda hanya dapat mengakses nilai dengan memanggil
get
metode.Keuntungan lain adalah bahwa kode menjadi lebih mudah dibaca . Dengan tambahan Java 9 ifPresentOrElse , fungsi tersebut bahkan dapat ditulis sebagai:
sumber
Optional
, masih ada banyak perpustakaan dan kerangka kerja yang menggunakan anotasi ini sehingga tidak layak untuk memperbarui / mengganti semua dependensi Anda dengan versi yang diperbarui untuk menggunakan Opsional.Optional
Namun dapat membantu dalam situasi di mana Anda menggunakan null dalam kode Anda sendiri.