Haruskah metode pengambilan mengembalikan 'nol' atau melemparkan pengecualian ketika tidak dapat menghasilkan nilai kembali? [Tutup]

503

Saya punya metode yang seharusnya mengembalikan objek jika ditemukan.

Jika tidak ditemukan, haruskah saya:

  1. kembali nol
  2. lempar pengecualian
  3. lain
Robert
sumber
57
Apa pun yang Anda lakukan, pastikan Anda mendokumentasikannya. Saya pikir poin ini lebih penting daripada pendekatan mana yang "terbaik".
Rik
6
Ini tergantung pada idiom bahasa pemrograman yang berlaku. Harap beri tag pertanyaan ini dengan tag bahasa pemrograman.
Teddy
3
Mengembalikan nol hanya berarti keberhasilan atau kegagalan yang sangat sering tidak banyak informasi (beberapa metode mungkin gagal dalam banyak hal). Perpustakaan harus lebih baik melemparkan pengecualian untuk membuat kesalahan eksplisit dan dengan cara ini program utama dapat memutuskan bagaimana menangani kesalahan pada tingkat yang lebih tinggi (berbeda dengan logika penanganan kesalahan bawaan).
3k-
1
Menurut saya pertanyaan sebenarnya yang diajukan adalah apakah kita harus menganggapnya luar biasa untuk sebuah entitas yang tidak ditemukan, dan jika demikian, mengapa? Tidak ada yang benar-benar menjawab secara memadai bagaimana sampai pada kesimpulan itu, dan sekarang Q&A ditutup. Sayang sekali bahwa industri belum mencapai konsensus tentang topik penting ini. Ya, saya tahu itu tergantung . Jadi, jelaskan mengapa itu tergantung dengan lebih dari "jika luar biasa, lempar"
naksir

Jawaban:

484

Jika Anda selalu berharap untuk menemukan nilai, maka lempar pengecualian jika nilai itu hilang. Pengecualian akan berarti bahwa ada masalah.

Jika nilainya dapat hilang atau ada dan keduanya valid untuk logika aplikasi, maka kembalikan nol.

Lebih penting: Apa yang Anda lakukan di tempat lain dalam kode? Konsistensi penting.

Ken
sumber
30
@ Ken: +1, akan menyenangkan untuk menyebutkan bahwa jika Anda benar-benar melempar pengecualian, tetapi dapat mendeteksinya secara apriori (seperti HasItem (...)), maka pengguna harus menyediakan metode Has * atau Contains.
user7116
4
Alih-alih mengembalikan nilai atau nol saat nilai tersebut hilang, pertimbangkan untuk mengembalikan Mungkin <T>. Lihat mikehadlow.blogspot.nl/2011/01/monads-in-c-5-maybe.html .
Erwin Rooijakkers
2
Dengan cara pilihan desain @ErwinRooijakkers , pada Java 8 Anda juga dapat mengembalikan Opsional <T>
José Andias
2
Saya merasa sedikit mengganggu setiap jawaban menggemakan pepatah yang sama: "Jika itu luar biasa, lempar." Sebagian besar insinyur akan terbiasa dengan prinsip ini. Menurut pendapat saya, pertanyaan sebenarnya di sini adalah bagaimana menentukan apakah itu harus dianggap luar biasa. OP sedang mencari praktik terbaik dalam hal seperti pola repositori misalnya. Apakah biasanya dianggap luar biasa untuk objek yang tidak ada diberikan kunci primer? Ya, itu adalah sesuatu yang akan ditentukan oleh domainnya, tetapi apa yang disarankan oleh sebagian besar pakar dengan pengalaman bertahun-tahun? Itu jenis jawaban yang harus kita lihat.
naksir
4
@ Crush Saya pikir prinsip panduan adalah parameter apa yang diteruskan ke fungsi . Jika Anda memberikan identitas , seperti Anda menyebutkan kunci utama, maka itu harus dianggap luar biasa jika item itu tidak ditemukan, karena itu menunjukkan keadaan yang tidak konsisten dalam sistem. Contoh: GetPersonById(25)akan melempar jika orang itu telah dihapus, tetapi GetPeopleByHairColor("red")akan mengembalikan hasil kosong. Jadi, saya pikir parameter mengatakan sesuatu tentang harapan.
John Knoop
98

Hanya melempar pengecualian jika ini benar-benar kesalahan. Jika perilaku yang diharapkan untuk objek tidak ada, kembalikan null.

Kalau tidak, itu adalah masalah preferensi.

Carlton Jenke
sumber
4
Saya tidak setuju. Anda dapat membuang pengecualian sebagai kode status: "NotFoundException"
ACV
Itu tentu tidak seharusnya menjadi masalah preferensi. Begitulah cara kita berakhir dengan kode yang tidak konsisten - jika bukan di antara kode tim Anda, maka hampir pasti ketika menjalin kode pengembang lain dengan kode Anda sendiri (perpustakaan eksternal).
naksir
4
Saya pikir menangani kasus nol jauh lebih mudah daripada "NotFoundException". Pikirkan tentang berapa banyak baris try-catch yang harus Anda tulis di sekitar setiap permintaan retrival tunggal yang melemparkan "NotFoundException" ... Sangat menyakitkan untuk menyiapkan semua kode itu di mata saya.
visc
Saya ingin mengutip Tony Hoare: "Saya menyebutnya kesalahan miliaran dolar saya". Saya tidak akan mengembalikan null, saya melempar pengecualian dan menanganinya dengan benar, atau mengembalikan objek kosong.
tujuh
70

Sebagai aturan umum, jika metode harus selalu mengembalikan objek, maka pergi dengan pengecualian. Jika Anda mengantisipasi null sesekali dan ingin menanganinya dengan cara tertentu, ikuti nol tersebut.

Apa pun yang Anda lakukan, saya sangat menyarankan terhadap opsi ketiga: Mengembalikan string yang mengatakan "WTF".

Matias Nino
sumber
Ditambah satu karena di masa lalu yang baik saya melakukan itu lebih dari beberapa kali sebagai perbaikan "temporal" kotor cepat ... tidak ada ide bagus. Khususnya jika itu akan ditinjau jika Anda seorang siswa.
rciafardone
14
Saya akan memilih sejak opsi WTF tampak luar biasa bagi saya ... tapi ternyata saya punya hati
swestner
5
membuang WtfExcepticeptn baru
Kamafeather
Saya pikir akan sangat membantu jika jawaban ini berbicara tentang alasan mengapa suatu metode akan selalu mengembalikan objek versus "nol sesekali". Apa yang menjamin situasi semacam itu? Berikan contoh kapan keadaan seperti itu mungkin ada.
naksir
51

Jika nol tidak pernah menunjukkan kesalahan maka kembalilah nol.

Jika nol selalu merupakan kesalahan maka lemparkan pengecualian.

Jika nol terkadang merupakan pengecualian maka kode dua rutinitas. Satu rutin melempar pengecualian dan yang lainnya adalah rutin uji boolean yang mengembalikan objek dalam parameter output dan rutin mengembalikan false jika objek tidak ditemukan.

Sulit untuk menyalahgunakan rutinitas Coba. Sangat mudah untuk lupa untuk memeriksa null.

Jadi ketika nol adalah kesalahan yang baru saja Anda tulis

object o = FindObject();

Ketika nol bukan kesalahan, Anda bisa mengkodekan sesuatu seperti

if (TryFindObject(out object o)
  // Do something with o
else
  // o was not found
Kevin Gale
sumber
1
Ini akan menjadi saran yang lebih berguna jika C # memberikan tupel nyata, sehingga kami dapat menghindari menggunakan parameter [keluar]. Namun, ini adalah pola yang disukai, jadi +1.
Erik Forbes
2
Menurut pendapat saya, pendekatan coba adalah yang terbaik. Anda tidak harus melihat ke atas lalu apa yang terjadi jika objek tidak dapat dikembalikan. Dengan metode Coba, Anda segera tahu apa yang harus dilakukan.
OregonGhost
mengingatkan saya pada finddan findOrFaildari Laravel
Eloquent
@ErikForbes Saya tahu komentar Anda sudah tua, tetapi bukankah jawabannya adalah mendefinisikan objek multi-properti yang akan dikembalikan dari TryFindObjectmetode ini? Tuples tampaknya lebih merupakan paradigma malas untuk programmer yang tidak ingin meluangkan waktu untuk mendefinisikan objek yang merangkum beberapa nilai. Itu pada dasarnya semua tuple pada intinya lagian.
naksir
@crush - Namle Tuple Literals adalah sebuah opsi, IMO. Ini adalah tautan ke pola Coba Dapatkan async dengan tupel. stackoverflow.com/questions/1626597/…
ttugates
26

Saya hanya ingin merekapitulasi opsi yang disebutkan sebelumnya, memasukkan beberapa opsi baru ke:

  1. kembali nol
  2. lempar Pengecualian
  3. gunakan pola objek nol
  4. berikan parameter boolean kepada Anda metode, sehingga pemanggil dapat memilih jika dia ingin Anda melemparkan pengecualian
  5. memberikan parameter tambahan, sehingga pemanggil dapat menetapkan nilai yang ia dapatkan kembali jika tidak ada nilai yang ditemukan

Atau Anda dapat menggabungkan opsi ini:

Berikan beberapa versi rajin Anda yang rajin, sehingga penelepon dapat memutuskan ke mana harus pergi. Dalam kebanyakan kasus, hanya yang pertama memiliki implementasi algoritma pencarian, dan yang lainnya hanya membungkus yang pertama:

Object findObjectOrNull(String key);
Object findObjectOrThrow(String key) throws SomeException;
Object findObjectOrCreate(String key, SomeClass dataNeededToCreateNewObject);
Object findObjectOrDefault(String key, Object defaultReturnValue);

Bahkan jika Anda memilih untuk menyediakan hanya satu implementasi, Anda mungkin ingin menggunakan konvensi penamaan seperti itu untuk memperjelas kontrak Anda, dan itu membantu Anda jika Anda pernah memutuskan untuk menambahkan implementasi lain juga.

Anda tidak boleh menggunakannya secara berlebihan, tetapi mungkin bermanfaat, terutama ketika menulis Kelas pembantu yang akan Anda gunakan dalam ratusan aplikasi yang berbeda dengan banyak konvensi penanganan kesalahan yang berbeda.

Lena Schimmel
sumber
Saya suka nama fungsi yang jelas, terutama orCreate dan orDefault.
marcovtwout
5
Sebagian besar ini dapat lebih bersih ditulis dengan Expected<T> findObject(String)mana Expected<T>memiliki fungsi orNull(), orThrow(), orSupplied(Supplier<T> supplier), orDefault(T default). Ini abstrak pengambilan data dari penanganan kesalahan
WorldSEnder
Saya tidak tahu tentang Diharapkan <T> sampai sekarang. Saya tampaknya cukup baru dan mungkin tidak ada ketika saya menulis jawaban yang asli. Mungkin Anda harus membuat komentar Anda sebagai jawaban yang tepat.
Lena Schimmel
Juga, Diharapkan <T> adalah template C ++. Apakah ada implementasi dalam bahasa berorientasi objek lain juga?
Lena Schimmel
Di Java 8, mengembalikan Opsional <T> (disebut Mungkin <T>, dll. Dalam bahasa lain) juga merupakan pilihan. Ini jelas menunjukkan kepada penelepon bahwa tidak mengembalikan apa-apa adalah suatu kemungkinan, dan tidak akan mengkompilasi jika penelepon tidak menangani kemungkinan itu, sebagai lawan dari nol, yang (di Jawa tetap) akan mengkompilasi bahkan jika penelepon tidak memeriksanya .
Some Guy
18

Gunakan pola objek nol atau lempar pengecualian.

pmlarocque
sumber
Inilah jawaban sebenarnya. Mengembalikan nol adalah kebiasaan buruk programmer yang malas.
jeremyjjbrown
Saya tidak percaya jawaban ini belum dipilih ke atas. Ini ADALAH jawaban nyata, dan pendekatan mana pun mudah mati dan menyimpan banyak kode-gembung atau NPE.
Bane
3
Jika seseorang menggunakan pola objek nol, bagaimana orang membedakan kasus di mana kunci dipetakan ke objek nol dari kasus di mana kunci tidak memiliki pemetaan? Saya akan berpikir mengembalikan objek yang tidak berarti akan jauh lebih buruk daripada mengembalikan null. Mengembalikan null ke kode yang tidak siap untuk menanganinya biasanya akan menghasilkan pengecualian. Bukan pilihan pengecualian yang optimal, tetapi sebuah pengecualian. Mengembalikan objek yang tidak berarti lebih cenderung menghasilkan kode yang salah tentang data yang tidak bermakna sebagai benar.
supercat
3
Bagaimana perilaku objek nol untuk pencarian entitas? Misalnya, Person somePerson = personRepository.find("does-not-exist");Mari kita asumsikan metode ini mengembalikan objek null untuk ID does-not-exist. Untuk apa perilaku yang benar somePerson.getAge()? Saat ini, saya belum yakin pola objek nol adalah solusi yang tepat untuk pencarian entitas.
Abdull
13

Konsisten dengan API yang Anda gunakan.

dmckee
sumber
13

Keuntungan melempar pengecualian:

  1. Aliran kontrol yang lebih bersih dalam kode panggilan Anda. Memeriksa null menyuntikkan cabang bersyarat yang ditangani secara native dengan coba / tangkap. Memeriksa null tidak menunjukkan apa yang Anda periksa - apakah Anda memeriksa nol karena Anda mencari kesalahan yang Anda harapkan, atau Anda memeriksa nol sehingga Anda tidak meneruskannya lebih jauh di downchain ?
  2. Menghapus ambiguitas dari arti "null". Apakah null mewakili kesalahan atau nol apa yang sebenarnya disimpan dalam nilai? Sulit dikatakan ketika Anda hanya memiliki satu hal yang mendasari tekad itu.
  3. Peningkatan konsistensi antara perilaku metode dalam suatu aplikasi. Pengecualian biasanya diekspos dalam tanda tangan metode, jadi Anda lebih bisa memahami apa tepi kasus metode dalam akun aplikasi untuk, dan informasi apa aplikasi Anda dapat bereaksi dengan cara yang dapat diprediksi.

Untuk penjelasan lebih lanjut dengan contoh, lihat: http://metatations.com/2011/11/17/returning-null-vs-throwing-an-exception/

Clifford Oravec
sumber
2
+1 karena titik 2 sangat baik - null tidak memiliki arti yang sama dengan yang tidak ditemukan. Ini menjadi lebih penting ketika berhadapan dengan bahasa dinamis di mana Null sebenarnya bisa menjadi objek yang disimpan / diambil oleh fungsi - dan dalam hal ini
Adam Terrey
1
+1 untuk poin # 2. Apakah null suatu kesalahan? Apakah null apa yang disimpan untuk kunci yang diberikan? Apakah nol indikatif bahwa kuncinya tidak ada? Ini adalah pertanyaan nyata yang membuat jelas kembali nol hampir tidak pernah benar. Ini mungkin jawaban terbaik di sini karena semua orang baru saja melempar ambigu "Jika itu luar biasa, lempar"
naksir
12

itu tergantung apakah bahasa dan kode Anda dipromosikan: LBYL (lihat sebelum Anda melompat) atau EAFP (lebih mudah untuk meminta maaf daripada izin)

LBYL mengatakan Anda harus memeriksa nilai-nilai (jadi kembalikan nol)
EAFP mengatakan untuk hanya mencoba operasi dan melihat apakah gagal (membuang pengecualian)

meskipun saya setuju dengan di atas .. pengecualian harus digunakan untuk kondisi luar biasa / kesalahan, dan mengembalikan nol adalah yang terbaik saat menggunakan cek.


EAFP vs. LBYL dalam Python:
http://mail.python.org/pipermail/python-list/2003-May/2051818.html ( Arsip Web )

Corey Goldberg
sumber
3
Dalam beberapa kasus, EAFP adalah satu-satunya pendekatan yang bermakna. Dalam peta / kamus bersamaan, misalnya, tidak ada cara untuk menanyakan apakah pemetaan akan ada saat diminta.
supercat
11

Tanyakan kepada diri sendiri: "apakah ini merupakan kasus luar biasa bahwa objek tidak ditemukan"? Jika diharapkan terjadi dalam program normal program Anda, Anda mungkin tidak boleh mengajukan pengecualian (karena itu bukan perilaku yang luar biasa).

Versi singkat: gunakan pengecualian untuk menangani perilaku luar biasa, bukan untuk menangani aliran kontrol normal dalam program Anda.

-Alan.

AlanR
sumber
5

Pengecualian terkait dengan Desain berdasarkan Kontrak.

Antarmuka suatu objek sebenarnya merupakan kontrak antara dua objek, pemanggil harus memenuhi kontrak atau penerima mungkin saja gagal dengan pengecualian. Ada dua kontrak yang mungkin

1) semua input metode ini valid, dalam hal ini Anda harus mengembalikan nol ketika objek tidak ditemukan.

2) hanya beberapa input yang valid, yaitu yang menghasilkan objek yang ditemukan. Dalam hal ini Anda HARUS menawarkan metode kedua yang memungkinkan penelepon untuk menentukan apakah inputnya akan benar. Sebagai contoh

is_present(key)
find(key) throws Exception

JIKA dan HANYA JIKA Anda memberikan kedua metode kontrak ke-2, Anda diizinkan untuk melemparkan pengecualian tidak ada yang ditemukan!

akuhn
sumber
4

Saya lebih suka mengembalikan nol, dan mengandalkan penelepon untuk menanganinya dengan tepat. Pengecualian (karena tidak ada kata yang lebih baik) adalah jika saya benar-benar 'yakin' metode ini akan mengembalikan objek. Dalam hal itu kegagalan adalah hal yang harus dan harus dilemparkan.

swilliams
sumber
4

Bergantung pada apa artinya benda itu tidak ditemukan.

Jika keadaan normal, maka kembalikan nol. Ini hanya sesuatu yang mungkin terjadi sesekali, dan penelepon harus memeriksanya.

Jika itu adalah kesalahan, lalu melempar pengecualian, penelepon harus memutuskan apa yang harus dilakukan dengan kondisi kesalahan objek yang hilang.

Pada akhirnya keduanya akan berfungsi, meskipun kebanyakan orang umumnya menganggap itu praktik yang baik untuk hanya menggunakan Pengecualian ketika sesuatu, yah, Luar Biasa telah terjadi.

Steve B.
sumber
2
Bagaimana Anda menguraikan pernyataan " keadaan normal " dan kriteria apa yang akan Anda gunakan untuk membedakannya dengan kesalahan.
user1451111
4

Berikut beberapa saran lagi.

Jika mengembalikan koleksi, hindari pengembalian nol, kembalikan koleksi kosong yang membuat penghitungan lebih mudah untuk ditangani tanpa cek nol terlebih dahulu.

Beberapa .NET API menggunakan pola parameter thrownOnError yang memberikan pemanggil pilihan apakah itu benar-benar situasi yang luar biasa atau tidak jika objek tidak ditemukan. Type.GetType adalah contoh dari ini. Pola umum lainnya dengan BCL adalah pola TryGet di mana boolean dikembalikan dan nilai dilewatkan melalui parameter output.

Anda juga bisa mempertimbangkan pola Objek Null dalam beberapa keadaan yang bisa menjadi default atau versi tanpa perilaku. Kuncinya adalah menghindari cek nol di seluruh basis kode. Lihat di sini untuk informasi lebih lanjut http://geekswithblogs.net/dsellers/archive/2006/09/08/90656.aspx

Duncan
sumber
3

Dalam beberapa fungsi saya menambahkan parameter:

..., bool verify = true)

Benar berarti melempar, salah berarti mengembalikan beberapa nilai pengembalian kesalahan. Dengan cara ini, siapa pun yang menggunakan fungsi ini memiliki kedua opsi. Defaultnya harus benar, untuk kepentingan mereka yang lupa tentang penanganan kesalahan.

Im
sumber
3

Kembalikan nol alih-alih melempar pengecualian dan jelas mendokumentasikan kemungkinan nilai pengembalian nol dalam dokumentasi API. Jika kode panggilan tidak menghormati API dan memeriksa kasus nol, kemungkinan besar akan menghasilkan semacam "pengecualian penunjuk nol" pula :)

Dalam C ++, saya dapat memikirkan 3 rasa berbeda dalam mengatur metode yang menemukan objek.

Opsi A

Object *findObject(Key &key);

Kembalikan nol ketika suatu objek tidak dapat ditemukan. Bagus dan sederhana. Saya akan memilih yang ini. Pendekatan alternatif di bawah ini adalah untuk orang-orang yang tidak membenci out-params.

Opsi B

void findObject(Key &key, Object &found);

Berikan referensi ke variabel yang akan menerima objek. Metode ini membuat pengecualian ketika suatu objek tidak dapat ditemukan. Konvensi ini mungkin lebih cocok jika itu tidak benar-benar diharapkan untuk suatu objek tidak ditemukan - maka Anda melemparkan pengecualian untuk menandakan bahwa itu adalah kasus yang tidak terduga.

Opsi C

bool findObject(Key &key, Object &found);

Metode mengembalikan false ketika suatu objek tidak dapat ditemukan. Keuntungan opsi over ini A adalah Anda dapat memeriksa kasus kesalahan dalam satu langkah yang jelas:

if (!findObject(myKey, myObj)) { ...
Ates Goral
sumber
3

hanya merujuk pada kasus di mana null tidak dianggap sebagai perilaku luar biasa saya pasti untuk metode coba, jelas, tidak perlu "membaca buku" atau "melihat sebelum Anda melompat" seperti yang dikatakan di sini

pada dasarnya:

bool TryFindObject(RequestParam request, out ResponseParam response)

dan ini berarti bahwa kode pengguna juga akan jelas

...
if(TryFindObject(request, out response)
{
  handleSuccess(response)
}
else
{
  handleFailure()
}
...
Sial
sumber
2

Jika penting untuk kode klien untuk mengetahui perbedaan antara ditemukan dan tidak ditemukan dan ini seharusnya menjadi perilaku rutin, maka yang terbaik adalah mengembalikan nol. Kode klien kemudian dapat memutuskan apa yang harus dilakukan.

alas tiang
sumber
2

Secara umum itu harus mengembalikan nol. Kode yang memanggil metode harus memutuskan apakah akan melempar pengecualian atau mencoba sesuatu yang lain.

Eran Galperin
sumber
2

Atau kembalikan Opsi

Opsi pada dasarnya adalah kelas kontainer yang memaksa klien untuk menangani kasing. Scala memiliki konsep ini, lihat API-nya.

Kemudian Anda memiliki metode seperti T getOrElse (T valueIfNull) pada objek ini yang dapat mengembalikan objek yang ditemukan, atau allternative yang ditentukan klien.

John Nilsson
sumber
2

Lebih suka mengembalikan nol -

Jika penelepon menggunakannya tanpa memeriksa, pengecualian terjadi di sana.

Jika penelepon tidak benar-benar menggunakannya, jangan mengenakan pajak pada a try/ catchblock

kizzx2
sumber
2

Sayangnya JDK tidak konsisten, jika Anda mencoba mengakses kunci yang tidak ada dalam bundel sumber daya, Anda tidak menemukan pengecualian dan ketika Anda meminta nilai dari peta Anda mendapatkan nol jika itu tidak ada. Jadi saya akan mengubah jawaban pemenang menjadi yang berikut, jika nilai yang ditemukan bisa nol, maka naikkan pengecualian ketika tidak ditemukan, jika tidak kembalikan nol. Jadi ikuti aturan dengan satu pengecualian, jika Anda perlu tahu mengapa nilai tidak ditemukan maka selalu naikkan pengecualian, atau ..

Dmitriy R
sumber
1

Selama itu seharusnya mengembalikan referensi ke objek, mengembalikan NULL harus baik.

Namun, jika itu mengembalikan seluruh hal yang berdarah (seperti di C ++ jika Anda melakukannya: 'return bla;' daripada 'return & bla;' (atau 'bla' adalah pointer), maka Anda tidak dapat mengembalikan NULL, karena itu bukan tipe 'objek'. Dalam hal itu, melemparkan pengecualian, atau mengembalikan objek kosong yang tidak memiliki kumpulan flag sukses adalah bagaimana saya akan mendekati masalah.

warren
sumber
1

Jangan berpikir ada orang yang menyebutkan overhead dalam penanganan pengecualian - membutuhkan sumber daya tambahan untuk memuat dan memproses pengecualian sehingga kecuali itu adalah aplikasi yang benar-benar membunuh atau memproses acara berhenti (maju akan menyebabkan lebih banyak kerugian daripada kebaikan) Saya akan memilih untuk melewatkan kembali nilai lingkungan panggilan bisa menafsirkan sesuai keinginan.

ScottCher
sumber
1

Saya setuju dengan apa yang tampaknya menjadi konsensus di sini (mengembalikan nol jika "tidak ditemukan" adalah hasil yang normal, atau melemparkan pengecualian jika semantik situasi mengharuskan objek selalu ditemukan).

Namun, ada kemungkinan ketiga yang mungkin masuk akal tergantung pada situasi khusus Anda. Metode Anda dapat mengembalikan objek default dalam kondisi "tidak ditemukan", yang memungkinkan kode panggilan diyakinkan bahwa ia akan selalu menerima objek yang valid tanpa perlu pengecekan nol atau penangkapan pengecualian.

GBegen
sumber
1

Kembalikan nol, pengecualian persis seperti itu: sesuatu yang dilakukan kode Anda yang tidak diharapkan.

Anders
sumber
1

Jika metode mengembalikan koleksi, lalu mengembalikan koleksi kosong (seperti dikatakan di atas). Tapi tolong jangan Collections.EMPTY_LIST atau semacamnya! (dalam hal Jawa)

Jika metode ini mengambil satu objek, maka Anda memiliki beberapa opsi.

  1. Jika metode ini harus selalu menemukan hasilnya dan ini merupakan perkecualian nyata untuk tidak menemukan objek, maka Anda harus melempar pengecualian (di Jawa: mohon Pengecualian tidak dicentang)
  2. (Hanya Java) Jika Anda bisa mentolerir metode melempar pengecualian yang dicentang, melempar ObjectNotFoundException khusus proyek atau sejenisnya. Dalam hal ini kompiler mengatakan Anda jika Anda lupa untuk menangani pengecualian. (Ini adalah penanganan pilihan saya untuk tidak menemukan hal-hal di Jawa.)
  3. Jika Anda mengatakan ini benar-benar ok, jika objek tidak ditemukan dan nama Metode Anda seperti findBookForAuthorOrReturnNull (..), maka Anda dapat mengembalikan nol. Dalam hal ini sangat disarankan untuk menggunakan semacam pemeriksaan statis atau pemeriksaan kompiler, yang mencegah dereferensi hasil tanpa pemeriksaan nol. Dalam kasus Jawa, bisa misalnya. FindBugs (lihat DefaultAnnotation di http://findbugs.sourceforge.net/manual/annotations.html ) atau Memeriksa IntelliJ.

Hati-hati, jika Anda memutuskan untuk mengembalikan nol. Jika Anda bukan satu-satunya programmer dalam proyek, Anda akan mendapatkan NullPointerExceptions (di Jawa atau apa pun dalam Bahasa lain) saat dijalankan! Jadi jangan mengembalikan nol yang tidak dicentang pada waktu kompilasi.

iuzuz
sumber
Tidak jika kode itu ditulis dengan benar untuk diharapkan null. Lihat jawaban terpilih untuk lebih banyak.
Andrew Barber
Tetapi hanya jika Anda memastikan pada waktu kompilasi, semua nol diperiksa. Ini dapat dilakukan, menggunakan FindBugs @NutNull di tingkat paket dan tandai metode Anda sebagai "dapat mengembalikan nol". Atau menggunakan bahasa seperti Kotlin atau Nice. Tetapi jauh lebih sederhana untuk tidak mengembalikan null.
iuzuz
"Lebih sederhana", mungkin . Tapi seringkali keliru
Andrew Barber
1
Sekali lagi: Baca jawaban terpilih untuk informasi lebih lanjut. Pada dasarnya: Jika itu adalah hasil yang diharapkan secara potensial bahwa buku yang diminta tidak dapat ditemukan, pengecualian adalah hal yang salah untuk dilakukan ketika buku yang diminta sama sekali tidak ditemukan, sebagai lawan dari beberapa kesalahan yang terjadi.
Andrew Barber
1
Anda banyak salah paham di sini. Anda menerapkan saran bersyarat secara universal, yang hampir selalu merupakan hal yang buruk untuk dilakukan. Baca sisa jawaban terpilih juga. Jawaban Anda hanya menyatakan absolut, dan menyajikan logika yang sangat salah untuk itu.
Andrew Barber
1

Jika Anda menggunakan perpustakaan atau kelas lain yang melempar pengecualian, Anda harus memikirkannya kembali. Berikut ini sebuah contoh. Example2.java seperti perpustakaan dan Example.java menggunakan objek itu. Main.java adalah contoh untuk menangani Pengecualian ini. Anda harus menunjukkan pesan yang bermakna dan (jika perlu) menumpuk jejak ke pengguna di sisi panggilan.

Main.java

public class Main {
public static void main(String[] args) {
    Example example = new Example();

    try {
        Example2 obj = example.doExample();

        if(obj == null){
            System.out.println("Hey object is null!");
        }
    } catch (Exception e) {
        System.out.println("Congratulations, you caught the exception!");
        System.out.println("Here is stack trace:");
        e.printStackTrace();
    }
}
}

Contoh.java

/**
 * Example.java
 * @author Seval
 * @date 10/22/2014
 */
public class Example {
    /**
     * Returns Example2 object
     * If there is no Example2 object, throws exception
     * 
     * @return obj Example2
     * @throws Exception
     */
    public Example2 doExample() throws Exception {
        try {
            // Get the object
            Example2 obj = new Example2();

            return obj;

        } catch (Exception e) {
            // Log the exception and rethrow
            // Log.logException(e);
            throw e;
        }

    }
}

Example2.java

 /**
 * Example2.java
 * @author Seval
 *
 */
public class Example2 {
    /**
     * Constructor of Example2
     * @throws Exception
     */
    public Example2() throws Exception{
        throw new Exception("Please set the \"obj\"");
    }

}
svlzx
sumber
Jika pengecualian yang dilemparkan dari fungsi bukan pengecualian runtime, dan penelepon diharapkan untuk menanganinya (bukan hanya menghentikan program), maka alih-alih melempar pengecualian dari subsistem internal yang tidak bisa diharapkan oleh penelepon, akan lebih baik untuk membungkus pengecualian internal dengan pengecualian diperiksa eksternal, sementara 'merantai' pengecualian internal sehingga seseorang debugging dapat mengetahui mengapa pengecualian eksternal dilemparkan. Misalnya, example1 dapat menggunakan 'throw new MyCheckedException ("Silakan setel \" obj \ "", e)' untuk memasukkan 'e' dalam pengecualian yang dilemparkan.
Some Guy
0

Itu sangat tergantung pada apakah Anda berharap untuk menemukan objek, atau tidak. Jika Anda mengikuti aliran pemikiran bahwa pengecualian harus digunakan untuk menunjukkan sesuatu, well, err, pengecualian telah terjadi kemudian:

  • Objek ditemukan; mengembalikan objek
  • Objek tidak ditemukan; membuang pengecualian

Jika tidak, kembalikan nol.

rampok
sumber