Mengapa tepatnya Java tidak mengizinkan persyaratan numerik seperti jika (5) {...} jika C tidak?

33

Saya punya dua program kecil ini:

C

#include <stdio.h>
int main()
{
    if (5) {
        printf("true\n");
    }
    else {
        printf("false\n");
    }

    return 0;
}

Jawa

class type_system {
   public static void main(String args[]) {
       if (5) {
           System.out.println("true");
       }
       else {
           System.out.println("false");
       }
   }
}

yang melaporkan pesan kesalahan:

type_system.java:4: error: incompatible types: int cannot be converted to boolean
       if (5) {
           ^
1 error

Pemahaman saya

Sejauh ini, saya mengerti contoh ini sebagai demonstrasi dari sistem tipe yang berbeda. Ketik C lebih lemah dan memungkinkan konversi dari int ke boolean tanpa kesalahan. Java lebih kuat diketik dan gagal, karena tidak ada percakapan implisit yang diizinkan.

Karena itu, pertanyaan saya: Di mana saya salah paham?

Apa yang tidak saya cari

Pertanyaan saya tidak terkait dengan gaya pengkodean yang buruk. Saya tahu itu buruk, tapi saya tertarik mengapa C mengizinkannya dan Java tidak. Oleh karena itu, saya tertarik pada sistem tipe bahasa, khususnya kekuatannya.

toogley
sumber
22
@toogley: Ada apa dengan sistem tipe di Jawa yang ingin Anda ketahui secara spesifik? Sistem tipe tidak mengizinkan ini karena spesifikasi bahasa melarangnya. Alasan mengapa C mengizinkannya dan Java tidak memiliki segalanya untuk dilakukan dengan apa yang dianggap dapat diterima dalam kedua bahasa. Perilaku yang dihasilkan dari sistem tipe adalah efek dari itu, bukan penyebabnya.
Robert Harvey
8
@toogley: menurut Anda mengapa Anda salah mengerti sesuatu? Membaca teks itu lagi, saya tidak mengerti apa pertanyaan Anda.
Doc Brown
26
Sebenarnya, ini bukan contoh dari pengetikan lemah pada C. Di masa lalu (C89), C bahkan tidak memiliki tipe boolean, jadi semua operasi "boolean" benar-benar beroperasi pada intnilai. Contoh yang lebih tepat adalah if (pointer).
Rufflewind
5
Saya tidak memilih karena sepertinya tidak banyak penelitian yang dilakukan untuk mencoba memahami hal ini.
jpmc26
11
Tampaknya pertanyaan awal yang diajukan sedikit berbeda dari versi yang diedit (itulah sebabnya beberapa komentar dan jawaban tampaknya menjawab pertanyaan yang berbeda). Dalam bentuknya saat ini, sepertinya tidak ada pertanyaan di sini. Kesalahpahaman apa? Java berperilaku persis seperti yang Anda pikirkan seharusnya.
jamesdlin

Jawaban:

134

1. C dan Java adalah bahasa yang berbeda

Fakta bahwa mereka berperilaku berbeda seharusnya tidak terlalu mengejutkan.

2. C tidak melakukan konversi dari intkebool

Bagaimana mungkin? C bahkan tidak memiliki booltipe yang benar untuk dikonversi hingga 1999 . C diciptakan pada awal 1970-an, dan ifmerupakan bagian dari itu sebelum itu bahkan C, kembali ketika itu hanya serangkaian modifikasi B 1 .

ifbukan hanya NOPdalam C selama hampir 30 tahun. Itu langsung bertindak pada nilai numerik. Kata-kata dalam standar C ( tautan PDF ), bahkan lebih dari satu dekade setelah pengenalan bools ke C, masih menentukan perilaku if(p 148) dan ?:(p 100) menggunakan istilah "tidak sama dengan 0" dan "sama dengan 0 "Daripada istilah Boolean" benar "atau" salah "atau yang serupa.

Dengan ...

3. ... angka kebetulan sesuai dengan instruksi prosesor yang beroperasi.

JZdan JNZinstruksi perakitan x86 dasar Anda untuk percabangan bersyarat. Singkatannya adalah " J ump if Z ero" dan " J ump if N ot Z ero". Setara dengan PDP-11, tempat asal C, adalah BEQ(" B ranch if EQ ual") dan BNE(" B ranch if N ot E qual").

Instruksi ini memeriksa apakah operasi sebelumnya menghasilkan nol atau tidak dan melompat (atau tidak) sesuai.

4. Java memiliki penekanan yang jauh lebih tinggi pada keselamatan daripada yang pernah dilakukan 2

Dan, dengan mempertimbangkan keselamatan, mereka memutuskan bahwa membatasi ifke booleans sepadan dengan biayanya (keduanya menerapkan pembatasan seperti itu dan biaya peluang yang dihasilkan).


1. B bahkan tidak memiliki tipe sama sekali. Bahasa assembly umumnya juga tidak. Namun B dan bahasa assembly berhasil menangani percabangan dengan baik.

2. Dalam kata-kata Dennis Ritchie ketika menggambarkan modifikasi yang direncanakan untuk B yang menjadi C (penekanan milikku):

... sepertinya diperlukan skema pengetikan untuk mengatasi karakter dan pengalamatan byte, dan untuk mempersiapkan perangkat keras floating-point yang akan datang. Masalah-masalah lain, terutama keamanan jenis dan pemeriksaan antarmuka, tidak tampak sama pentingnya dengan yang terjadi kemudian.

8bree
sumber
13
Poin bagus tentang ekspresi boolean dalam pemetaan C langsung ke instruksi prosesor. Saya belum memikirkan hal itu sebelumnya.
Robert Harvey
17
Saya pikir poin 4 menyesatkan karena tampaknya menyiratkan C memiliki sedikit fokus keselamatan ... C akan membiarkan Anda melakukan apa pun yang Anda inginkan pada dasarnya: C menganggap Anda tahu apa yang Anda lakukan, sering kali dengan hasil yang spektakuler.
TemporalWolf
13
@TemporalWolf Anda menyatakan bahwa seolah-olah membiarkan Anda melakukan apa yang Anda inginkan itu buruk. Perbedaan pendapat saya adalah bahwa C ditulis untuk programmer dan kompetensi dasar diharapkan. Java ditulis untuk kode monyet dan jika Anda bisa mengetik Anda bisa memprogram di dalamnya. Seringkali luar biasa buruk tetapi siapa yang peduli bukan? Saya tidak akan pernah lupa ketika seorang guru di kelas java pengantar saya dipaksa untuk mengambil sebagai bagian dari minor CS saya, menunjukkan bahwa menggunakan rekursi untuk menghitung angka Fibonnaci mungkin berguna karena itu "mudah untuk menulis". Itu sebabnya kami memiliki perangkat lunak yang kami miliki.
DRF
25
@DRF Salah satu profesor saya untuk kelas jaringan C mengatakan, "C seperti sekotak granat tangan dengan semua pin ditarik." Anda memiliki banyak kekuatan, tetapi pada dasarnya dijamin akan meledak di wajah Anda. Dalam sebagian besar kasus, itu tidak sepadan dengan kerumitannya, dan Anda akan jauh lebih produktif dengan bahasa tingkat yang lebih tinggi. Sudahkah saya mentranskode Python ke dalam hacky C bit-twiddling untuk mendapatkan 6 kali peningkatan kecepatan? Ya, ya saya punya. Tapi itu pengecualian, bukan aturannya. Saya dapat menyelesaikan dalam satu hari dengan Python apa yang akan membawa saya dua minggu dalam C ... dan saya seorang programmer C yang layak.
TemporalWolf
11
@DRF Mengingat prevalensi eksploitasi buffer overflow dalam perangkat lunak utama yang dikembangkan oleh perusahaan papan atas, tampaknya bahkan programmer dengan kompetensi dasar tidak dapat dipercaya untuk tidak menyerang mereka.
Pasang kembali Monica
14

C 2011 Draf Online

6.8.4.1 ifPernyataan

Kendala

1 Ekspresi pengontrol suatu ifpernyataan harus memiliki tipe skalar.

Semantik

2 Dalam kedua bentuk, substatemen pertama dieksekusi jika ekspresi membandingkan tidak sama dengan 0. Dalam elseform, subtatement kedua dieksekusi jika ekspresinya sama dengan 0. Jika substatement pertama dicapai melalui label, substatement kedua adalah tidak dieksekusi.

3 An elsedikaitkan dengan leksikal terdekat sebelumnya jika itu diizinkan oleh sintaks.

Perhatikan bahwa klausa ini hanya menentukan bahwa ekspresi pengontrol harus memiliki tipe skalar ( char/ short/ int/ long/ dll.), Tidak secara khusus tipe Boolean. Cabang dijalankan jika ekspresi pengontrol memiliki nilai bukan nol.

Bandingkan dengan

Spesifikasi Bahasa Java SE 8

14,9 The ifPernyataan

The ifpernyataan memungkinkan eksekusi bersyarat dari pernyataan atau pilihan bersyarat dua pernyataan, mengeksekusi satu atau yang lain tetapi tidak keduanya.
    IfThenStatement :
        jika ( Expression ) Pernyataan

    IfThenElseStatement :
        jika ( Expression ) StatementNoShortIf lain Pernyataan

    IfThenElseStatementNoShortIf :
        if ( Ekspresi ) StatementNoShortIf else StatementNoShortIf
The Ekspresi harus memiliki tipe booleanatau Boolean, atau kesalahan saat kompilasi terjadi.

Java, OTOH, secara khusus mensyaratkan bahwa ekspresi pengontrol dalam ifpernyataan memiliki tipe Boolean.

Jadi, ini bukan tentang pengetikan lemah vs. pengetikan, ini tentang apa yang masing-masing definisi bahasa tentukan sebagai ekspresi kontrol yang valid.

Edit

Adapun mengapa bahasa berbeda dalam hal ini, beberapa poin:

  1. C diturunkan dari B, yang merupakan bahasa "tanpa huruf" - pada dasarnya, semuanya adalah kata 32-36-bit (tergantung pada perangkat keras), dan semua operasi aritmatika adalah operasi integer. Sistem tipe C melesat sedikit demi sedikit, sehingga ...

  2. C tidak memiliki tipe Boolean yang berbeda sampai versi bahasa 1999. C cukup mengikuti konvensi B untuk menggunakan nol untuk mewakili falsedan bukan nol untuk mewakili true.

  3. Java pasca-tanggal C oleh beberapa dekade yang baik, dan dirancang khusus untuk mengatasi beberapa kekurangan C dan C ++. Tidak diragukan lagi memperketat pembatasan pada apa yang mungkin menjadi ekspresi kontrol dalam ifpernyataan adalah bagian dari itu.

  4. Tidak ada alasan untuk mengharapkan setiap dua bahasa pemrograman untuk melakukan hal-hal dengan cara yang sama. Bahkan bahasa yang memiliki kaitan erat seperti C dan C ++ berbeda dalam beberapa cara yang menarik, sehingga Anda dapat memiliki program C legal yang bukan program C ++ legal, atau program C ++ legal tetapi dengan semantik berbeda, dll.

John Bode
sumber
Terlalu sedih, saya tidak dapat menandai dua jawaban sebagai "diterima" ..
toogley
1
Ya, ini adalah pernyataan ulang yang bagus untuk pertanyaan itu. Tetapi pertanyaannya adalah mengapa ada perbedaan antara kedua bahasa ini. Anda belum membahas ini sama sekali.
Dawood mengatakan mengembalikan Monica
@ DawoodibnKareem: Pertanyaannya adalah mengapa C mengizinkan konversi dari intke booleansementara Java tidak. Jawabannya adalah tidak ada konversi seperti itu dalam C. Bahasa berbeda karena mereka adalah bahasa yang berbeda.
John Bode
Ya, "ini bukan tentang pengetikan lemah vs. kuat". Lihat saja kotak otomatis dan kotak otomatis. Jika C memiliki itu, itu juga tidak memungkinkan tipe skalar.
Deduplicator
5

Banyak jawaban tampaknya menargetkan ekspresi penugasan tertanam yang ada dalam ekspresi bersyarat. (Walaupun itu adalah jenis jebakan potensial yang diketahui, itu bukan sumber pesan kesalahan Java dalam kasus ini.)

Mungkin ini karena OP tidak mempublikasikan pesan kesalahan yang sebenarnya, dan, ^tanda sisipan menunjuk langsung ke =operator penugasan.

Namun kompiler menunjuk ke =karena itu adalah operator yang menghasilkan nilai akhir (dan karenanya jenis terakhir) dari ekspresi yang dilihat oleh kondisi.

Mengeluh tentang pengujian nilai non-boolean, dengan jenis kesalahan berikut:

error: jenis yang tidak kompatibel: int tidak dapat dikonversi ke boolean

Bilangan bulat pengujian, meskipun terkadang mudah, dianggap sebagai perangkap potensial yang harus dihindari oleh perancang Java. Setelah semua, Java memiliki tipe data boolean benar , yang C tidak tidak (tidak memiliki tipe boolean) .

Ini juga berlaku untuk pointer pengujian C untuk null / non-null via if (p) ...dan if (!p) ..., yang Java juga tidak mengizinkan sebaliknya membutuhkan operator pembanding eksplisit untuk mendapatkan boolean yang diperlukan.

Erik Eidt
sumber
1
C memang memiliki tipe boolean. Tapi itu lebih baru dari ifpernyataan itu.
MSalters
3
@MSalters C's bool masih merupakan bilangan bulat di bawah selimut, maka Anda dapat melakukannya bool b = ...; int v = 5 + b;. Ini berbeda dengan bahasa dengan tipe boolean penuh yang tidak dapat digunakan dalam aritmatika.
Jules
Boolean C hanyalah bilangan bulat yang sangat kecil. "true" dan "false" dapat dengan mudah didefinisikan dengan makro atau apa pun.
Oskar Skog
4
@ Jules: Anda hanya menunjukkan bahwa C memiliki keamanan jenis yang lemah. Hanya karena tipe boolean mengkonversi ke nilai integer tidak berarti itu adalah tipe integer. Menurut logika Anda, tipe integer adalah tipe floating-point karena int v = 5; float f = 2.0 + v;legal di C.
MSalters
1
@MSalters sebenarnya _Booladalah salah satu tipe integer standar yang tidak ditandatangani sebagaimana didefinisikan oleh Standar (lihat 6.2.5 / 6).
Ruslan
2

tipe tidak kompatibel: int tidak dapat dikonversi ke boolean

Saya tertarik pada mengapa C mengizinkannya dan java tidak. Oleh karena itu, saya tertarik pada sistem tipe bahasa, khususnya kekuatannya.

Ada dua bagian untuk pertanyaan Anda:

Mengapa Java tidak mengkonversi intke boolean?

Ini bermuara pada Jawa yang dimaksudkan untuk menjadi sejelas mungkin. Ini sangat statis, sangat "di wajahmu" dengan sistem tipenya. Hal-hal yang secara otomatis diketik-ketik dalam bahasa lain tidak demikian, di Jawa. Anda harus menulis int a=(int)0.5juga. Konversi floatke intakan kehilangan informasi; sama dengan mengonversi intke booleandan karenanya akan rawan kesalahan. Juga, mereka harus menentukan banyak kombinasi. Tentu, hal-hal ini tampaknya jelas, tetapi mereka bermaksud berbuat salah di sisi kehati-hatian.

Oh, dan dibandingkan dengan bahasa lain, Java sangat tepat dalam spesifikasinya, karena bytecode bukan hanya detail implementasi internal. Mereka harus menentukan interaksi apa saja dan semua, tepatnya. Usaha besar.

Mengapa iftidak menerima tipe lain selain boolean?

ifdapat dengan sempurna didefinisikan untuk memungkinkan jenis selain boolean. Itu bisa memiliki definisi yang mengatakan yang berikut ini setara:

  • true
  • int != 0
  • String dengan .length>0
  • Referensi objek lain yang bukan null(dan bukan Booleandengan nilai false).
  • Atau bahkan: referensi objek lain yang bukan- nulldan metode yang Object.check_if(ditemukan oleh saya hanya untuk kesempatan ini) kembali true.

Mereka tidak; tidak ada kebutuhan nyata, dan mereka ingin memilikinya sekuat, statis, transparan, mudah dibaca dll. mungkin. Tidak ada fitur implisit. Juga, implementasinya akan sangat kompleks, saya yakin, harus menguji setiap nilai untuk semua kasus yang mungkin, jadi kinerja mungkin memainkan faktor kecil juga (Java dulu sloooow di komputer pada hari itu; ingat ada tidak ada kompiler JIT dengan rilis pertama, setidaknya tidak pada komputer yang saya gunakan saat itu).

Alasan yang lebih dalam

Alasan yang lebih dalam adalah fakta bahwa Jawa memiliki tipe primitifnya, karenanya sistem tipenya terbelah antara objek dan primitif. Mungkin, jika mereka menghindari itu, segalanya akan berubah dengan cara lain. Dengan aturan yang diberikan pada bagian sebelumnya, mereka harus mendefinisikan kebenaran dari setiap primitif secara eksplisit (karena primitif tidak berbagi kelas super, dan tidak ada yang didefinisikan dengan baik nulluntuk primitif). Ini akan berubah menjadi mimpi buruk, dengan cepat.

Pandangan

Yah, dan pada akhirnya, mungkin itu hanya preferensi para perancang bahasa. Setiap bahasa tampaknya berputar sendiri di sana ...

Misalnya, Ruby tidak memiliki tipe primitif. Semuanya, secara harfiah segalanya, adalah objek. Mereka memiliki waktu yang sangat mudah untuk memastikan bahwa setiap objek memiliki metode tertentu.

Ruby memang mencari kebenaran pada semua jenis objek yang bisa Anda lemparkan padanya. Yang cukup menarik, masih tidak memiliki booleantipe (karena tidak memiliki primitif), dan tidak memiliki Booleankelas juga. Jika Anda bertanya pada kelas berapa nilainya true(tersedia dengan mudah true.class), Anda dapatkan TrueClass. Kelas itu sebenarnya memiliki metode, yaitu 4 operator untuk boolean ( | & ^ ==). Di sini, ifanggap falsey nilainya jika dan hanya jika salah satu falseatau nil( nullRuby). Yang lainnya benar. Jadi, 0atau ""keduanya benar.

Sepele bagi mereka untuk menciptakan metode Object#truthy?yang dapat diterapkan untuk kelas apa pun dan mengembalikan kebenaran individu. Misalnya, String#truthy?bisa diterapkan untuk string yang tidak kosong, atau yang lainnya. Mereka tidak, meskipun Ruby adalah antitesis Jawa di sebagian besar departemen (mengetik bebek dinamis dengan mixin, membuka kembali kelas dan semua itu).

Yang mungkin mengejutkan bagi seorang programmer Perl yang terbiasa $value <> 0 || length($value)>0 || defined($value)menjadi kebenaran. Dan seterusnya.

Masukkan SQL dengan konvensi bahwa nulldi dalam setiap ekspresi secara otomatis membuatnya salah, apa pun yang terjadi. Jadi (null==null) = false. Di Ruby (nil==nil) = true,. Saat-saat bahagia.

AnoE
sumber
Sebenarnya, ((int)3) * ((float)2.5)cukup didefinisikan dengan baik di Jawa 7.5f.
Paŭlo Ebermann
Anda benar, @ PaŭloEbermann, saya telah menghapus contoh itu.
AnoE
Woah di sana ... akan menghargai komentar dari downvoters dan orang yang memilih untuk benar-benar menghapus jawabannya.
AnoE
Sebenarnya konversi dari intke floatjuga kehilangan informasi secara umum. Apakah Java juga melarang pemeran tersirat tersebut?
Ruslan
@Ruslan no (sama untuk long → double) - Saya kira idenya adalah bahwa kehilangan informasi potensial hanya ada di tempat yang paling tidak signifikan, dan hanya terjadi dalam kasus yang dianggap tidak begitu penting (nilai integer yang cukup besar).
Paŭlo Ebermann
1

Selain jawaban bagus lainnya, saya ingin berbicara tentang konsistensi antar bahasa.

Ketika kita memikirkan pernyataan if yang murni secara matematis, kita memahami bahwa kondisinya dapat benar atau salah, tidak ada nilai lain. Setiap bahasa pemrograman utama menghormati ideal matematika ini; jika Anda memberikan nilai Boolean true / false pada pernyataan if, maka Anda dapat berharap untuk melihat perilaku yang konsisten dan intuitif sepanjang waktu.

Sejauh ini baik. Inilah yang Java implementasikan, dan hanya Java yang implementasikan.

Bahasa lain mencoba menghadirkan kenyamanan untuk nilai-nilai non-Boolean. Sebagai contoh:

  • Misalkan nbilangan bulat. Sekarang tentukan if (n)sebagai singkatan if (n != 0).
  • Misalkan xadalah angka floating-point. Sekarang tentukan if (x)sebagai singkatan if (x != 0 && !isNaN(x)).
  • Misalkan padalah tipe pointer. Sekarang tentukan if (p)sebagai singkatan if (p != null).
  • Misalkan sadalah tipe string. Sekarang tentukan if (s)menjadi if (s != null && s != "").
  • Misalkan aadalah tipe array. Sekarang tentukan if (a)menjadi if (a != null && a.length > 0).

Gagasan memberikan steno jika-tes ini tampaknya bagus di permukaan ... sampai Anda menemukan perbedaan dalam desain dan pendapat:

  • if (0)diperlakukan sebagai false dalam C, Python, JavaScript; tetapi diperlakukan sebagai benar di Ruby.
  • if ([]) diperlakukan sebagai false dalam Python tetapi benar dalam JavaScript.

Setiap bahasa memiliki alasan sendiri yang baik untuk memperlakukan ekspresi dengan satu atau lain cara. (Misalnya, satu-satunya nilai palsu di Ruby adalah falsedan nil, karenanya 0benar.)

Java mengadopsi desain eksplisit untuk memaksa Anda untuk memasok nilai Boolean ke pernyataan if. Jika Anda dengan tergesa-gesa menerjemahkan kode dari C / Ruby / Python ke Java, Anda tidak dapat meninggalkan kelemahan jika-tes tidak berubah; Anda perlu menuliskan kondisi secara eksplisit di Jawa. Meluangkan waktu sejenak untuk berhenti dan berpikir dapat menyelamatkan Anda dari kesalahan yang ceroboh.

Nayuki
sumber
1
Apakah Anda tahu itu x != 0sama dengan x != 0 && !isNaN(x)? Juga, biasanya s != nulluntuk pointer, tetapi sesuatu yang lain untuk non-pointer.
Deduplicator
@Dupuplikator dalam bahasa apa itu sama?
Paŭlo Ebermann
1
Menggunakan IEEE754, NaN ≠ 0. NaN ≠ apa saja. Jadi jika (x) akan mengeksekusi, dan jika (! X) akan mengeksekusi juga ...
gnasher729
0

Ya, setiap tipe skalar dalam C, pointer, boolean (sejak C99), angka (floating-point atau tidak) dan enumerasi (karena pemetaan langsung ke angka) memiliki nilai falsey "alami", jadi itu cukup baik untuk ekspresi bersyarat apa pun .

Java juga memilikinya (bahkan jika pointer Java disebut referensi dan sangat dibatasi), tetapi Java memperkenalkan tinju otomatis di Jawa 5.0 yang membuat air tidak dapat diterima. Juga, programmer Java mendesak nilai intrinsik mengetik lebih banyak.

Satu kesalahan yang memicu perdebatan apakah membatasi ekspresi kondisional ke tipe boolean adalah kesalahan penulisan tugas di mana perbandingan dimaksudkan, yang tidak ditangani dengan membatasi tipe ekspresi kondisional sama sekali , tetapi dengan melarang penggunaan penugasan-ekspresi telanjang untuk nilainya.

Setiap kompiler C atau C ++ modern menangani dengan mudah, memberikan peringatan atau kesalahan untuk konstruksi yang dipertanyakan seperti itu jika diminta.
Untuk kasus-kasus di mana persis seperti yang dimaksudkan, menambahkan tanda kurung membantu.

Untuk meringkas, membatasi ke boolean (dan setara kotak di Jawa) tampak seperti upaya gagal untuk membuat kelas kesalahan ketik yang disebabkan oleh memilih =untuk tugas-kesalahan kompilasi.

Deduplicator
sumber
Menggunakan ==dengan operan boolean, yang mana yang pertama adalah variabel (yang kemudian bisa dengan ketik =) di dalam ifterjadi jauh lebih jarang daripada dengan jenis lain, saya akan mengatakan, jadi itu hanya upaya semi-gagal.
Paŭlo Ebermann
Memiliki 0,0 -> false dan nilai apa pun selain 0,0 -> true sama sekali tidak terlihat "alami" bagi saya.
gnasher729
@ PaŭloEbermann: Hasil sebagian dengan efek samping yang tidak menguntungkan, sementara ada cara mudah untuk mencapai tujuan tanpa efek samping, adalah kegagalan yang jelas dalam buku saya.
Deduplicator
Anda melewatkan alasan lainnya. Bagaimana dengan nilai truthy dari "", (Object) "", 0.0, -0.0, NaN, array kosong, dan Boolean.FALSE? Terutama yang terakhir lucu, karena itu pointer non-null (true) yang membuka kotak ke false. +++ Saya juga benci menulis if (o != null), tetapi menyelamatkan saya beberapa karakter setiap hari dan membiarkan saya menghabiskan setengah hari men-debug ekspresi "pintar" saya bukanlah hal yang bagus. Karena itu, saya ingin melihat jalan tengah untuk Jawa: Aturan yang lebih murah hati tetapi tidak meninggalkan ambiguitas sama sekali.
maaartinus
@maaartinus: Seperti yang saya katakan, pengenalan auto-unboxing di Java 5.0 berarti jika mereka menetapkan nilai kebenaran yang berkaitan dengan null-ness ke pointer, mereka akan memiliki masalah yang cukup besar. Tapi itu masalah dengan tinju otomatis (bukan), bukan hal lain. Bahasa tanpa tinju otomatis (tidak) seperti C dengan senang hati bebas dari itu.
Deduplicator
-1

Pertanyaan saya tidak terkait dengan gaya pengkodean yang buruk. Saya tahu itu buruk, tapi saya intersted mengapa C tidak mengizinkannya dan java tidak.

Dua tujuan desain Jawa adalah:

  1. Izinkan pengembang untuk fokus pada masalah bisnis. Jadikan hal-hal lebih sederhana dan tidak terlalu rentan kesalahan, misalnya pengumpulan sampah sehingga pengembang tidak perlu fokus pada kebocoran memori.

  2. Portable antar platform, mis. Berjalan di komputer mana saja dengan CPU apa pun.

Penggunaan penugasan sebagai ungkapan diketahui menyebabkan banyak bug karena kesalahan pengetikan, jadi berdasarkan tujuan # 1 di atas, itu tidak diizinkan seperti yang Anda coba menggunakannya.

Juga, menyimpulkan bahwa nilai bukan nol = benar dan nilai nol apa pun = salah tidak harus portabel (ya, percaya atau tidak, beberapa sistem memperlakukan 0 sebagai benar dan 1 sebagai salah ), jadi berdasarkan tujuan # 2 di atas, tidak diperbolehkan secara implisit . Anda masih dapat melakukan casting secara eksplisit tentunya.

John Wu
sumber
4
Kecuali jika ditambahkan di Java 8, tidak ada pemeran eksplisit antara tipe numerik dan Boolean. Untuk mengonversi nilai numerik ke Boolean, Anda harus menggunakan operator perbandingan; untuk mengonversi nilai Boolean ke nilai numerik Anda biasanya menggunakan operator ternary.
Peter Taylor
Anda dapat membuat kasus untuk melarang penggunaan tugas karena nilainya karena kesalahan ketik tersebut. Tetapi mengingat seberapa sering Anda melihat == true dan == false di Java, jelas membatasi ekspresi kontrol untuk tipe boolean (opsional) tidak terlalu membantu.
Deduplicator
Java akan dengan mudah memastikan portabilitas wrt ke "beberapa sistem memperlakukan 0 sebagai benar dan 1 sebagai salah" karena itu adalah nol di Jawa dan salah di Jawa. Tidak masalah apa yang dipikirkan OS tentang hal itu.
maaartinus
-1

Sebagai contoh apa yang dilakukan bahasa lain: Swift memerlukan ekspresi tipe yang mendukung protokol "BooleanType", yang artinya harus memiliki metode "boolValue". Tipe "bool" jelas mendukung protokol ini dan Anda dapat membuat tipe Anda sendiri yang mendukungnya. Jenis integer tidak mendukung protokol ini.

Dalam versi yang lebih lama dari bahasa, tipe opsional mendukung "BooleanType" sehingga Anda dapat menulis "jika x" bukannya "jika x! = Nil". Yang dibuat dengan menggunakan "bool opsional" sangat membingungkan. Bool opsional memiliki nilai nil, false atau true dan "jika b" tidak akan dieksekusi jika b adalah nil dan dieksekusi jika b benar atau salah. Ini tidak diizinkan lagi.

Dan tampaknya ada satu orang yang benar-benar tidak suka membuka cakrawala Anda ...

gnasher729
sumber