Kapan nilai null dari Boolean digunakan?

159

Java booleanmemungkinkan nilai-nilai truedan falsesementara Boolean memungkinkan true, false, dan null. Saya sudah mulai mengonversi booleans ke Booleans. Ini dapat menyebabkan crash pada tes seperti

Boolean set = null;
...
if (set) ...

saat tes

if (set != null && set) ...

tampaknya dibuat-buat dan rawan kesalahan.

Kapan, jika pernah, apakah berguna untuk menggunakan Booleans dengan nilai nol? Jika tidak pernah, lalu apa keuntungan utama dari objek yang dibungkus?

PEMBARUAN: Ada begitu banyak jawaban yang berharga sehingga saya merangkumnya dalam jawaban saya sendiri. Saya paling tidak perantara di Jawa jadi saya telah mencoba menunjukkan hal-hal yang menurut saya berguna. Perhatikan bahwa pertanyaannya adalah "salah mengartikan" (Boolean tidak dapat "memiliki nilai nol") tetapi saya telah meninggalkannya seandainya orang lain memiliki kesalahpahaman yang sama

peter.murray.rust
sumber
7
Terkadang, Anda ingin keadaan yang tidak diinisialisasi, dan mengatur Booleanvariabel untuk nullmembantu.
nhahtdh
3
"Selalu" agak kuat sehingga saya tidak berani mengkonfirmasi, tapi saya akan mengharapkan tes untuk nullapakah itu benar-benar digunakan sebagai kondisi ke-3.
nhahtdh
6
Apakah Anda punya alasan untuk mengubah booleans ke Booleans? Saya akan tetap menggunakan tipe primitif dan membungkusnya hanya jika ada alasan yang baik untuk melakukannya, misalnya ketika saya harus melewatkan variabel dengan referensi.
jpe
7
Anda juga mungkin ingin memeriksa ini: thedailywtf.com/Articles/What_Is_Truth_0x3f_.aspx
biziclop
6
Tidak ada yang namanya "nilai nol dalam Boolean". A Booleanadalah objek, sedangkan a booleanadalah "skalar". Jika Booleanreferensi disetel ke nol, berarti objek yang bersangkutan Booleantidak ada. Anda tidak dapat menempatkan apa pun di dalam sesuatu yang tidak ada.
Hot Licks

Jawaban:

244

Gunakan booleandaripada Booleansetiap kali Anda bisa. Ini akan menghindari banyak NullPointerExceptions dan membuat kode Anda lebih kuat.

Boolean berguna, misalnya

  • untuk menyimpan booleans dalam koleksi (Daftar, Peta, dll.)
  • untuk mewakili boolean yang dapat dibatalkan (misalnya, berasal dari kolom boolean yang dapat dibatalkan dalam database). Nilai nol mungkin berarti "kita tidak tahu apakah itu benar atau salah" dalam konteks ini.
  • setiap kali suatu metode membutuhkan Objek sebagai argumen, dan Anda harus memberikan nilai boolean. Misalnya, ketika menggunakan refleksi atau metode suka MessageFormat.format().
JB Nizet
sumber
35
Nilai nol dalam database juga bisa berarti "FileNotFound"
Karl Johan
31
Peluru kedua Anda benar-benar inti dari jawaban yang tepat untuk pertanyaan ini, saya pikir.
Niels Brinch
3
Kegunaan lain untuk Boolean yang saya miliki adalah sebagai parameter tipe generik ketika memperluas kelas generik - terkait erat dengan poin 3.
Alex
6
Membebani konsep nol dengan makna selain "alam semesta tidak tahu" lebih lemah daripada menggunakan 3 (atau lebih) enum yang bernilai. Membuat membaca parameter lewat parameter ke dalam metode lebih eksplisit juga.
bluevector
16
Atau # 4: Boolean isSchrodinger‎CatAlive = null;(maaf, tidak bisa menahan;))
Matthieu
58

Saya hampir tidak pernah menggunakan Booleankarena semantiknya tidak jelas dan tidak jelas. Pada dasarnya Anda memiliki logika 3-state: true, false atau tidak diketahui. Terkadang berguna untuk menggunakannya ketika misalnya Anda memberi pengguna pilihan antara dua nilai dan pengguna tidak menjawab sama sekali dan Anda benar-benar ingin mengetahui informasi itu (pikirkan: kolom database NULLable).

Saya tidak melihat alasan untuk mengkonversi dari booleanke Booleanseperti memperkenalkan overhead memori tambahan, NPE kemungkinan dan kurang mengetik. Biasanya saya menggunakan canggung BooleanUtils.isTrue()untuk membuat hidup saya sedikit lebih mudah Boolean.

Satu-satunya alasan keberadaan Booleanadalah kemampuan untuk memiliki koleksi Booleanjenis (generik tidak memungkinkan boolean, serta semua primitif lainnya).

Tomasz Nurkiewicz
sumber
1
Meskipun demikian, ini adalah perpustakaan eksternal (Apache commons).
nhahtdh
4
Untuk logika multinilai, lebih baik menggunakan enum. Dengan demikian Boolean harus dibiarkan untuk variabel tinju (otomatis) untuk digunakan dalam struktur data.
jpe
39
Saat menggunakan Boolean, tes yang mudah untuk menghindari pengecualian null pointer adalah Boolean.TRUE.equals(myBooleanObject)atau Boolean.FALSE.equals(myBooleanObject).
Christopher Peisert
10
Objek Boolean hanya memiliki dua negara - truedan false. nulladalah tidak keadaan objek, melainkan keadaan referensi obyek.
Hot Licks
2
Biarkan apache commons menjadi seperti "Seseorang mungkin mengacaukan mengevaluasi boolean ... mari kita membuat isTrue()metode ..." yang terdengar seperti hal paling bodoh dalam sejarah fungsi utilitas. Namun, entah bagaimana, ini berguna ... itulah yang terbesar di sini.
corsiKa
33

Wow, apa-apaan ini? Apakah hanya saya atau apakah semua jawaban ini salah atau paling tidak menyesatkan?

Kelas Boolean adalah pembungkus di sekitar tipe primitif boolean. Penggunaan pembungkus ini adalah untuk dapat melewati boolean dalam metode yang menerima objek atau generik. Yaitu vektor.

Objek Boolean TIDAK PERNAH memiliki nilai nol. Jika referensi Anda ke Boolean adalah nol, itu berarti bahwa Boolean Anda tidak pernah dibuat.

Anda mungkin menemukan ini berguna: http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/lang/Boolean.java

Referensi Boolean nol seharusnya hanya digunakan untuk memicu logika yang sama dengan yang Anda punya referensi nol lainnya. Menggunakannya untuk logika tiga negara adalah kikuk.

EDIT: perhatikan, itu Boolean a = true;adalah pernyataan yang menyesatkan. Ini benar-benar sama dengan sesuatu yang lebih dekat dengan Boolean a = new Boolean(true); Silakan lihat autoboxing di sini: http://en.wikipedia.org/wiki/Boxing_%28computer_science%29#Autoboxing

Mungkin dari sinilah banyak kebingungan muncul.

EDIT2: Silakan baca komentar di bawah ini. Jika ada yang punya ide bagaimana merestrukturisasi jawaban saya untuk memasukkan ini, silakan lakukan.

pengguna606723
sumber
2
Saya tidak mengerti pernyataan Anda "Boolean TIDAK PERNAH memiliki nilai nol". Saya bisa membuat Boolean ( Boolean a = true;) dan kemudian mengatur ke null ( a = null;). Mungkin tidak elegan atau tidak, tetapi mungkin saja.
peter.murray.rust
7
Kapan Anda melakukannya Boolean a; a adalah pointer ke objek Boolean. Jika Anda a = null;Anda belum menetapkan Boolean Anda ke nol, Anda telah menetapkan referensi Anda ke nol. Apakah Boolean a = null; a.booleanValue();Dalam kasus ini, Anda bahkan tidak pernah membuat objek Boolean dan karena itu akan melempar nullpointerexception. Beritahu saya jika Anda membutuhkan instruksi lebih lanjut.
user606723
Selanjutnya, ketika Anda melakukannya Boolean a = true;, itu melakukan semacam sihir yang benar-benar ditafsirkan sebagai Boolean a = new Boolean(true);Thats mungkin tidak sepenuhnya benar karena alasan kinerja, tetapi Anda harus menyadari bahwa Boolean masih merupakan objek.
user606723
7
@missingno, Semua kode yang berhubungan dengan objek apa pun harus berurusan dengan ini. Referensi objek dapat berupa null atau tidak. Ini bukan kasus khusus dan tidak memerlukan pertimbangan khusus.
user606723
3
Anda kehilangan poin saya @missingno. Saya setuju bahwa kami perlu mempertimbangkan nilai referensi nol. Saya tidak pernah membantah hal itu. Tetapi kita perlu melakukan ini untuk REFERENSI OBYEK APA PUN. Referensi null Boolean bukan kasus khusus. Dan karenanya nilai referensi Boolean nol tidak memerlukan pertimbangan khusus.
user606723
24

Ada tiga alasan cepat:

  • untuk mewakili nilai-nilai boolean Database, yang mungkin true, falseataunull
  • untuk mewakili xsd:booleannilai - nilai Skema XML yang dideklarasikan denganxsd:nillable="true"
  • untuk dapat menggunakan tipe generik: List<Boolean> - Anda tidak dapat menggunakanList<boolean>
Grzegorz Grzybek
sumber
Saya secara eksplisit telah menulis "boolean", bukan " boolean" (styling gaya), karena di Oracle Anda biasanya menggunakan char(1) nulldengan nilai 'T' dan 'F'. Jadi mungkin (dengan misalnya, adaptor tipe Hibernate) menjadi nol :)
Grzegorz Grzybek
2
Database apa yang tidak mengizinkan null untuk boolean? Jika Anda mengatur kolom menjadi nullable, tipe data tidak penting lagi ...
Michal B.
@MichalB. Jenis bit Sybase (dan SQL Server) infocenter.sybase.com/help/index.jsp?topic=/…
mmmmmm
@ Mark - tidak, SQL Server memang memungkinkan bit nullable - msdn.microsoft.com/en-us/library/ms177603.aspx
David M
11

JAWABAN UNTUK PERTANYAAN SENDIRI: Saya pikir akan bermanfaat untuk menjawab pertanyaan saya sendiri karena saya telah belajar banyak dari jawabannya. Jawaban ini dimaksudkan untuk membantu mereka - seperti saya - yang tidak memiliki pemahaman lengkap tentang masalah ini. Jika saya menggunakan bahasa yang salah tolong perbaiki saya.

  • "Nilai" nol bukan nilai dan pada dasarnya berbeda dari truedan false. Ini adalah tidak adanya pointer ke objek. Karenanya berpikir bahwa Boolean bernilai 3 pada dasarnya salah
  • Sintaks untuk Boolean disingkat dan menyembunyikan fakta bahwa referensi menunjuk ke Objek:

    Boolean a = true;

menyembunyikan fakta bahwa itu trueadalah objek. Tugas setara lainnya mungkin:

Boolean a = Boolean.TRUE;

atau

Boolean a = new Boolean(true);
  • Sintaks yang disingkat

    if (a) ...

berbeda dari kebanyakan penugasan lainnya dan menyembunyikan fakta bahwa a dapat berupa referensi objek atau primitif. Jika suatu objek perlu diuji untuk nullmenghindari NPE. Bagi saya, secara psikologis lebih mudah untuk mengingat ini jika ada tes kesetaraan:

if (a == true) ...

tempat kami mungkin diminta menguji nol. Jadi bentuk yang dipersingkat hanya aman saata primitif.

Bagi saya sendiri sekarang saya memiliki rekomendasi:

  • Jangan pernah gunakan null untuk logika bernilai 3. Hanya gunakan benar dan salah.
  • JANGAN PERNAH kembali Booleandari suatu metode sebagaimana mestinya null. Hanya kembaliboolean .
  • Hanya gunakan Booleanuntuk membungkus elemen dalam wadah, atau argumen untuk metode di mana objek diperlukan
peter.murray.rust
sumber
5
Jangan gunakan "Boolean baru (apa pun)". Itu akan membuat Instanate Boolean baru di heap. Namun Boolean tidak berubah. Gunakan "Boolean.valueOf (apa pun)" yang akan membuat referensi yang menunjuk ke Boolean.TRUE atau Boolean.False tergantung pada apa pun.
simbo1905
1
Salah satu dari banyak masalah dengan Java (IMHO setelah 12 tahun) adalah ketidakkonsistenan pendekatan terhadap nilai-nilai nol yang juga dimiliki bahasa-bahasa lama. Melihat Scala, ia memiliki konsep Opsi yang diketik yang bisa nol atau dapat memiliki nilai (subkelas Tidak Ada atau Sebagian). Kemudian Anda dapat memanggil myOption.getOrElse (defaultValue). Lihat scala-lang.org/api/current/scala/Option.html tidak ada yang rumit tentang fitur ini. Namun karena itu dibangun ke dalam bahasa JVM baru banyak perpustakaan menggunakannya. Itu membuat skala "memperbaiki" beberapa masalah "abad terakhir" dari Java tetapi masih mengkompilasi ke file kelas yang berjalan pada JRE.
simbo1905
10

Kelas wrapper untuk primitif dapat digunakan di mana objek diperlukan, koleksi adalah sampel yang baik.

Bayangkan Anda perlu untuk beberapa toko alasan urutan booleandalam ArrayList, ini dapat dilakukan dengan tinju booleandi Boolean.

Ada beberapa kata tentang ini di sini

Dari dokumentasi:

Seperti yang diketahui oleh setiap programmer Java, Anda tidak bisa memasukkan int (atau nilai primitif lainnya) ke dalam koleksi. Koleksi hanya bisa menampung referensi objek, jadi Anda harus memasukkan nilai primitif ke dalam kelas wrapper yang sesuai (yang merupakan Integer dalam kasus int). Saat Anda mengeluarkan objek dari koleksi, Anda mendapatkan Integer yang Anda masukkan; jika Anda memerlukan int, Anda harus membuka kotak Integer menggunakan metode intValue. Semua tinju dan unboxing ini menyakitkan, dan mengacaukan kode Anda. Fitur autoboxing dan unboxing mengotomatiskan proses, menghilangkan rasa sakit dan kekacauan.

http://docs.oracle.com/javase/1.5.0/docs/guide/language/autoboxing.html

Francisco Spaeth
sumber
3

Booleanbungkus berguna ketika Anda ingin apakah nilai ditugaskan atau tidak terlepas dari truedan false. Ini memiliki tiga negara berikut:

  • Benar
  • Salah
  • Tidak ditentukan yang mana null

Sedangkan booleanhanya memiliki dua negara:

  • Benar
  • Salah

Perbedaan di atas akan membantu dalam Daftar Booleannilai, yang dapat dimiliki True, Falseatau Null.

Ramesh PVK
sumber
Tidak, itu tidak memiliki keadaan nol, itu rujukannya.
Matsemann
Yang saya maksudkan adalah Bolean dapat digunakan untuk didefinisikan Benar / Salah dan Tidak Ditentukan.
Ramesh PVK
3

Saya kira dalam beberapa kasus, Anda harus memiliki mekanisme untuk membedakan bidang Boolean yang sudah menetapkan nilai atau tidak.

Thinhbk
sumber
1

Tujuan utama untuk Boolean adalah nilai nol. Nilai Null mengatakan, properti itu tidak terdefinisi , misalnya mengambil kolom database nullable.

Jika Anda benar-benar perlu mengonversi everyting dari primitif boolean ke wrapper Boolean, maka Anda dapat menggunakan yang berikut untuk mendukung kode lama:

Boolean set = Boolean.FALSE; //set to default value primitive value (false)
...
if (set) ...
Jelnik
sumber
6
'Tujuan utamanya adalah nilai nol'. Tidak, tujuan utama Boolean adalah memberikan referensi ke boolean sebagai objek.
user606723
@ user606723 setuju, saya mengacu pada kasus basis data dalam pikiran saya ketika saya sedang menulis.
JMelnik
1

Ada banyak kegunaan untuk nilai ** null ** di bungkus Boolean! :)

Misalnya, Anda mungkin memiliki formulir yang bernama "buletin" yang mengindikasikan apakah pengguna ingin atau tidak ingin buletin dari situs Anda. Jika pengguna tidak memilih nilai di bidang ini, Anda mungkin ingin menerapkan perilaku default untuk situasi itu (kirim? Jangan kirim ?, pertanyaan lagi?, Dll). Jelas, tidak disetel (atau tidak dipilih atau ** null **), tidak sama dengan benar atau salah.

Tetapi, jika "tidak disetel" tidak berlaku untuk model Anda, jangan ubah boolean primitive;)

dcasanueva
sumber
1

Dalam definisi yang ketat dari elemen boolean, hanya ada dua nilai. Di dunia yang sempurna, itu benar. Di dunia nyata, elemen tersebut mungkin hilang atau tidak diketahui. Biasanya, ini melibatkan input pengguna. Dalam sistem berbasis layar, itu bisa dipaksa oleh suntingan. Dalam dunia batch menggunakan basis data atau input XML, elemen dapat dengan mudah hilang.

Jadi, di dunia non-sempurna yang kita tinggali, objek Boolean hebat karena dapat mewakili keadaan yang hilang atau tidak dikenal sebagai nol. Bagaimanapun, komputer hanya memodelkan dunia nyata dan harus memperhitungkan semua kemungkinan keadaan dan menanganinya dengan melempar pengecualian (kebanyakan karena ada kasus penggunaan di mana melempar pengecualian akan menjadi jawaban yang benar).

Dalam kasus saya, objek Boolean adalah jawaban yang sempurna karena input XML terkadang memiliki elemen yang hilang dan saya masih bisa mendapatkan nilai, menugaskannya ke Boolean dan kemudian memeriksa nol sebelum mencoba menggunakan tes benar atau salah dengan itu .

Hanya 2 sen saya.

pengguna3228876
sumber
1

Untuk semua jawaban yang baik di atas, saya hanya akan memberikan contoh konkret di HttpSessionkelas servlet Java . Semoga contoh ini membantu menjelaskan beberapa pertanyaan yang mungkin masih Anda miliki.

Jika Anda perlu menyimpan dan mengambil nilai untuk suatu sesi, Anda menggunakan metode setAttribute(String, Object), dan getAttribute(String, Object). Jadi untuk nilai boolean, Anda terpaksa menggunakan kelas Boolean jika Anda ingin menyimpannya dalam sesi http.

HttpSession sess = request.getSession(false);
Boolean isAdmin = (Boolean) sess.getAttribute("admin");
if (! isAdmin) ...

Baris terakhir akan menyebabkan a NullPointerExceptionjika nilai atribut tidak disetel. (yang merupakan alasan membawaku ke pos ini). Jadi 3 keadaan logika di sini untuk tetap, apakah Anda lebih suka menggunakannya atau tidak.

Wacker
sumber
0

Cara terbaik adalah menghindari boolean sepenuhnya, karena setiap boolean menyiratkan bahwa Anda memiliki pernyataan bersyarat di tempat lain dalam kode Anda (lihat http://www.antiifcampaign.com/ dan pertanyaan ini: Dapatkah Anda menulis algoritma apa pun tanpa pernyataan if ? ).

Namun, secara pragmatis Anda harus menggunakan booleans dari waktu ke waktu, tetapi, seperti yang sudah Anda ketahui sendiri, berurusan dengan Booleans lebih rentan kesalahan dan lebih rumit. Jadi saya sarankan menggunakan boolean sedapat mungkin. Pengecualian dari ini mungkin merupakan database lama dengan kolom boolean yang dapat dibatalkan, meskipun saya akan mencoba menyembunyikannya dalam pemetaan saya juga.

Roland Schneider
sumber
Berurusan dengan Boolean sama rawan kesalahannya dengan berurusan dengan Objek lain. BTW, tautannya menentang proliferasi IF untuk pemeriksaan jenis, bukan untuk penggunaan umum. Dan pada gilirannya, itu "berbahaya" karena membuat modifikasi lebih sulit. Jadi tidak ada yang salah dengan IFs per se.
Tuan Smith
Bukan jawaban untuk pertanyaan itu.
Matsemann
@MisterSmith Imho bendera boolean sering disalahgunakan sebagai variabel pengecekan tipe, sehingga tautannya juga berlaku di sini. Seharusnya itu hanya petunjuk bahwa orang harus berpikir tentang apakah boolean adalah alat yang tepat dalam situasi tertentu. Pernyataan "hindari boolean sepenuhnya" tentu saja sangat radikal dan praktis tidak mungkin, mengapa saya menambahkan paragraf kedua. Saya juga menambahkan "lebih banyak kesalahan cenderung dan lebih rumit" untuk mengklarifikasi hal-hal.
Roland Schneider
0

Boolean bisa sangat membantu ketika Anda membutuhkan tiga negara. Seperti dalam pengujian perangkat lunak jika Uji lulus kirim benar, jika gagal kirim palsu dan jika uji kasus terganggu kirim nol yang akan menunjukkan uji kasus tidak dieksekusi.

Aamir
sumber
2
Bukankah enum adalah yang terbaik untuk ini? Berbeda dengan kemungkinan menghasilkan NullPointerExceptions yang tidak terduga untuk klien, enum akan secara eksplisit mendefinisikan "negara"
Kartik Chugh
Selalu lebih suka enum daripada boolean di mesin negara. Anda tidak pernah tahu kapan negara keempat baru tiba dalam persyaratan bisnis.
AnupamChugh