Setelah berdiskusi dengan beberapa kolega saya, saya memiliki pertanyaan 'filosofis' tentang bagaimana memperlakukan tipe data char di Jawa, mengikuti praktik terbaik.
Misalkan skenario sederhana (jelas ini hanya contoh yang sangat sederhana untuk memberikan makna praktik pada pertanyaan saya) di mana, dengan memberikan String 's sebagai input, Anda harus menghitung jumlah karakter numerik yang ada di dalamnya.
Ini adalah 2 solusi yang mungkin:
1)
for(int i=0; i<s.length(); i++) {
if(s.charAt(i) >= 48 && s.charAt(i) <= 57) {
n++;
}
}
2)
for(int i=0; i<s.length(); i++) {
if(s.charAt(i) >= '0' && s.charAt(i) <= '9' ) {
n++;
}
}
Manakah dari keduanya yang lebih 'bersih' dan sesuai dengan praktik terbaik Java?
VK_
konstanta yang seharusnya Anda gunakan, kedua menggunakan kode char lebih baik daripada char Java adalah jenis bahasa yang aman Anda tidak seharusnya melakukan pemeriksaan cross-type. @Brandin Ini disebut praktik pengkodeanVK_*
Konstanta berhubungan dengan kunci bukan karakter .Jawaban:
Keduanya mengerikan, tetapi yang pertama lebih mengerikan.
Keduanya mengabaikan kemampuan bawaan Java untuk memutuskan karakter apa yang "numerik" (melalui metode dalam
Character
). Tetapi yang pertama tidak hanya mengabaikan sifat Unicode dari string, dengan asumsi bahwa hanya ada 0123456789, itu juga mengaburkan alasan yang tidak valid ini dengan menggunakan kode karakter yang masuk akal hanya jika Anda tahu sesuatu tentang sejarah pengkodean karakter.sumber
matches("[0-9]+")
, daripada mengeksploitasi trik rentang yang termotivasi secara historis.Tidak juga. Biarkan kelas karakter bawaan Java mengetahuinya untuk Anda.
Ada beberapa rentang karakter lebih banyak daripada digit ASCII yang dihitung sebagai digit, dan tidak ada contoh yang Anda poskan yang akan menghitungnya. The javadoc untuk
Character.isDigit()
daftar rentang karakter ini sebagai angka yang valid:Yang sedang berkata, seseorang harus mendelegasikan
Character.isDigit()
bahkan dengan daftar ini. Saat pesawat Unicode baru terisi, kode Java akan diperbarui. Memutakhirkan JVM dapat membuat kode lama berfungsi dengan karakter digit baru dengan mulus. Ini juga KERING : dengan melokalkan kode "apakah ini angka" ke satu tempat yang dirujuk di tempat lain, aspek negatif dari duplikasi kode (yaitu bug) dapat dihindari. Akhirnya, perhatikan baris terakhir: daftar ini tidak lengkap, dan ada angka lainnya.Secara pribadi, saya lebih suka mendelegasikan ke perpustakaan Java inti dan menghabiskan waktu saya untuk tugas-tugas yang lebih produktif daripada "mencari apa yang digit."
Satu-satunya pengecualian untuk aturan ini adalah jika Anda benar-benar perlu menguji digit ASCII literal dan bukan digit lainnya. Misalnya, jika Anda menguraikan aliran dan hanya digit ASCII (yang bertentangan dengan digit lainnya) yang memiliki makna khusus, maka itu tidak akan sesuai untuk digunakan
Character.isDigit()
.Dalam hal ini, saya akan menulis metode lain, misalnya
MyClass.isAsciiDigit()
dan memasukkan logika di sana. Anda mendapatkan manfaat yang sama dari penggunaan kembali kode, namanya sangat jelas untuk memeriksa, dan logikanya benar.sumber
Jika Anda pernah menulis aplikasi dalam C yang menggunakan EBCDIC sebagai set karakter dasar dan perlu memproses karakter ASCII maka gunakan
48
dan57
. Apakah kamu melakukan itu? Saya kira tidak.Tentang menggunakan
isDigit()
: itu tergantung. Apakah Anda menulis parser JSON? Hanya0
untuk9
diterima sebagai angka, jadi jangan gunakanisDigit()
, periksa>= '0'
dan<= '9'
. Apakah Anda memproses input pengguna? GunakanisDigit()
selama sisa kode Anda benar-benar dapat menangani string dan mengubahnya menjadi angka dengan benar.sumber
Contoh kedua jelas lebih unggul. Arti dari contoh kedua langsung jelas ketika Anda melihat kode. Arti dari contoh pertama hanya jelas jika Anda telah menghafal seluruh tabel ASCII di kepala Anda.
Anda harus membedakan antara memeriksa karakter tertentu, atau memeriksa rentang atau kelas karakter.
1) Memeriksa karakter tertentu.
Untuk karakter biasa, gunakan karakter literal, mis
if(ch=='z')...
. , . Jika Anda mengecek karakter khusus seperti tab atau break baris, Anda harus menggunakan lolos, sepertiif (ch=='\n')...
. Jika karakter yang Anda periksa tidak biasa (mis. Tidak segera dikenali atau tidak tersedia pada keyboard standar), Anda mungkin menggunakan kode karakter hex daripada karakter literal. Tetapi karena kode hex adalah "nilai ajaib", Anda akan mengekstraknya ke sebuah konstanta dan mendokumentasikannya:Kode hex adalah cara standar untuk menentukan kode karakter.
2) Memeriksa kelas atau rentang karakter
Anda benar-benar tidak boleh melakukan ini secara langsung dalam kode aplikasi, tetapi harus merangkumnya dalam kelas terpisah yang hanya berkaitan dengan klasifikasi karakter. Dan Anda harus bervariasi dari ini, karena perpustakaan sudah ada untuk tujuan ini, dan klasifikasi karakter biasanya lebih kompleks daripada yang Anda pikirkan, setidaknya jika Anda mempertimbangkan karakter di luar rentang ASCII.
Jika Anda hanya peduli tentang karakter dalam rentang ASCII, Anda bisa menggunakan literal karakter di perpustakaan ini, jika tidak, Anda mungkin akan menggunakan hex-literal. Jika Anda melihat kode sumber untuk pustaka karakter Java builtin, itu juga merujuk ke nilai karakter dan rentang menggunakan heksadesimal, karena ini adalah bagaimana mereka ditentukan dalam standar Unicode.
sumber
'\x2603'
bukannya secara eksplisit bahwa Anda menguji nilai untuk karakter dengan pengkodean heksadesimal dan bukan sembarang nomor acak.Itu selalu lebih baik untuk digunakan
c >= '0'
karena untukc >= 48
Anda perlu mengkonversi c dalam kode ascii.sumber
Ekspresi Reguler ( RegEx s) memiliki kelas karakter khusus untuk digit -
\d
- yang dapat digunakan untuk menghapus karakter lain dari string Anda. Panjang string yang dihasilkan adalah nilai yang diinginkan.Perhatikan, bagaimanapun, bahwa RegEx s secara komputasi lebih menuntut daripada solusi yang diusulkan lainnya karena itu mereka seharusnya tidak disukai secara umum .
sumber