Apa saja contoh kehidupan nyata untuk memahami peran kunci dari pernyataan?
Apa saja contoh kehidupan nyata untuk memahami peran kunci dari pernyataan?
Jawaban:
Penegasan (dengan kata kunci penegasan ) ditambahkan di Java 1.4. Mereka digunakan untuk memverifikasi kebenaran invarian dalam kode. Mereka tidak boleh dipicu dalam kode produksi, dan merupakan indikasi bug atau penyalahgunaan jalur kode. Mereka dapat diaktifkan pada saat dijalankan dengan menggunakan -ea
opsi pada java
perintah, tetapi tidak diaktifkan secara default.
Sebuah contoh:
public Foo acquireFoo(int id) {
Foo result = null;
if (id > 50) {
result = fooService.read(id);
} else {
result = new Foo(id);
}
assert result != null;
return result;
}
assert
untuk memeriksa parameter metode publik ( docs.oracle.com/javase/1.4.2/docs/guide/lang/assert.html ). Itu harus membuang Exception
bukannya membunuh program.
This convention is unaffected by the addition of the assert construct. Do not use assertions to check the parameters of a public method. An assert is inappropriate because the method guarantees that it will always enforce the argument checks. It must check its arguments whether or not assertions are enabled. Further, the assert construct does not throw an exception of the specified type. It can throw only an AssertionError.
docs.oracle.com/javase/8/docs/technotes/guides/language/…
Mari kita asumsikan bahwa Anda seharusnya menulis sebuah program untuk mengendalikan pembangkit listrik tenaga nuklir. Sangat jelas bahwa kesalahan yang paling kecil sekalipun dapat memiliki hasil yang sangat besar, oleh karena itu kode Anda harus bebas bug (dengan asumsi bahwa JVM bebas bug untuk kepentingan argumen).
Java bukan bahasa yang dapat diverifikasi, yang berarti: Anda tidak dapat menghitung bahwa hasil operasi Anda akan sempurna. Alasan utama untuk ini adalah pointer: mereka dapat menunjuk di mana saja atau di mana saja, oleh karena itu mereka tidak dapat dihitung dengan nilai yang tepat ini, setidaknya tidak dalam rentang kode yang masuk akal. Mengingat masalah ini, tidak ada cara untuk membuktikan bahwa kode Anda benar secara keseluruhan. Tetapi yang dapat Anda lakukan adalah membuktikan bahwa Anda setidaknya menemukan setiap bug ketika itu terjadi.
Ide ini didasarkan pada paradigma Design-by-Contract (DbC): pertama-tama Anda mendefinisikan (dengan ketepatan matematis) apa yang seharusnya dilakukan oleh metode Anda, dan kemudian memverifikasi ini dengan mengujinya selama eksekusi aktual. Contoh:
// Calculates the sum of a (int) + b (int) and returns the result (int).
int sum(int a, int b) {
return a + b;
}
Meskipun ini cukup jelas untuk bekerja dengan baik, sebagian besar programmer tidak akan melihat bug tersembunyi di dalam yang satu ini (petunjuk: Ariane V jatuh karena bug yang sama). Sekarang DbC mendefinisikan bahwa Anda harus selalu memeriksa input dan output dari suatu fungsi untuk memverifikasi bahwa itu berfungsi dengan benar. Java dapat melakukan ini melalui pernyataan:
// Calculates the sum of a (int) + b (int) and returns the result (int).
int sum(int a, int b) {
assert (Integer.MAX_VALUE - a >= b) : "Value of " + a + " + " + b + " is too large to add.";
final int result = a + b;
assert (result - a == b) : "Sum of " + a + " + " + b + " returned wrong sum " + result;
return result;
}
Jika fungsi ini sekarang gagal, Anda akan melihatnya. Anda akan tahu bahwa ada masalah dalam kode Anda, Anda tahu di mana itu dan Anda tahu apa yang menyebabkannya (mirip dengan Pengecualian). Dan yang lebih penting: Anda berhenti mengeksekusi saat itu terjadi untuk mencegah kode lebih lanjut bekerja dengan nilai yang salah dan berpotensi menyebabkan kerusakan pada apa pun yang dikontrolnya.
Pengecualian Java adalah konsep yang serupa, tetapi mereka gagal memverifikasi semuanya. Jika Anda menginginkan lebih banyak cek (dengan biaya kecepatan eksekusi) Anda perlu menggunakan pernyataan. Melakukan hal itu akan mengasapi kode Anda, tetapi pada akhirnya Anda dapat mengirimkan produk pada waktu pengembangan yang sangat singkat (semakin cepat Anda memperbaiki bug, semakin rendah biayanya). Dan sebagai tambahan: jika ada bug di dalam kode Anda, Anda akan mendeteksinya. Tidak ada bug yang lolos dan menyebabkan masalah di kemudian hari.
Ini masih bukan jaminan untuk kode bebas bug, tetapi lebih dekat dengan itu, daripada program biasa.
new IllegalArgumentException
pesan? Maksudku, selain harus menambahkan throws
deklarasi metode dan kode untuk mengelola pengecualian itu di tempat lain. Mengapa assert
harus membuang Exception baru? Atau mengapa bukan yang if
bukan assert
? Tidak bisa mendapatkan ini :(
a
bisa negatif. Pernyataan kedua tidak berguna; untuk nilai int, selalu terjadi bahwa + b - b == a. Tes itu hanya bisa gagal jika komputer pada dasarnya rusak. Untuk bertahan dari kemungkinan itu, Anda perlu memeriksa konsistensi di beberapa CPU.
Pernyataan adalah alat fase pengembangan untuk menangkap bug dalam kode Anda. Mereka dirancang agar mudah dihapus, sehingga tidak akan ada dalam kode produksi. Jadi pernyataan bukan bagian dari "solusi" yang Anda berikan kepada pelanggan. Itu adalah pemeriksaan internal untuk memastikan bahwa asumsi yang Anda buat benar. Contoh paling umum adalah menguji nol. Banyak metode ditulis seperti ini:
void doSomething(Widget widget) {
if (widget != null) {
widget.someMethod(); // ...
... // do more stuff with this widget
}
}
Sangat sering dalam metode seperti ini, widget seharusnya tidak pernah menjadi nol. Jadi jika itu nol, ada bug di kode Anda di suatu tempat yang harus Anda lacak. Tetapi kode di atas tidak akan pernah memberi tahu Anda hal ini. Jadi dalam upaya yang bermaksud baik untuk menulis kode "aman", Anda juga menyembunyikan bug. Jauh lebih baik menulis kode seperti ini:
/**
* @param Widget widget Should never be null
*/
void doSomething(Widget widget) {
assert widget != null;
widget.someMethod(); // ...
... // do more stuff with this widget
}
Dengan cara ini, Anda pasti akan mengetahui bug ini lebih awal. (Ini juga berguna untuk menentukan dalam kontrak bahwa parameter ini tidak boleh nol.) Pastikan untuk mengaktifkan pernyataan ketika Anda menguji kode Anda selama pengembangan. (Dan membujuk kolega Anda untuk melakukan ini, juga seringkali sulit, yang menurut saya sangat menjengkelkan.)
Sekarang, beberapa kolega Anda akan keberatan dengan kode ini, dengan alasan bahwa Anda masih harus memasukkan cek nol untuk mencegah pengecualian dalam produksi. Dalam hal ini, pernyataan itu masih bermanfaat. Anda bisa menulis seperti ini:
void doSomething(Widget widget) {
assert widget != null;
if (widget != null) {
widget.someMethod(); // ...
... // do more stuff with this widget
}
}
Dengan cara ini, kolega Anda akan senang bahwa cek nol ada untuk kode produksi, tetapi selama pengembangan, Anda tidak lagi menyembunyikan bug ketika widget nol.
Inilah contoh dunia nyata: Saya pernah menulis sebuah metode yang membandingkan dua nilai arbitrer untuk kesetaraan, di mana salah satu nilai bisa nol:
/**
* Compare two values using equals(), after checking for null.
* @param thisValue (may be null)
* @param otherValue (may be null)
* @return True if they are both null or if equals() returns true
*/
public static boolean compare(final Object thisValue, final Object otherValue) {
boolean result;
if (thisValue == null) {
result = otherValue == null;
} else {
result = thisValue.equals(otherValue);
}
return result;
}
Kode ini mendelegasikan pekerjaan equals()
metode dalam kasus di mana Nilai ini bukan nol. Tapi itu mengasumsikan equals()
metode memenuhi kontrak equals()
dengan benar dengan benar menangani parameter nol.
Seorang kolega keberatan dengan kode saya, memberi tahu saya bahwa banyak dari kelas kami memiliki equals()
metode buggy yang tidak menguji nol, jadi saya harus memasukkan cek itu ke dalam metode ini. Dapat diperdebatkan apakah ini bijaksana, atau jika kita harus memaksakan kesalahan, sehingga kita dapat menemukannya dan memperbaikinya, tetapi saya menunda kolega saya dan memasukkan cek nol, yang saya tandai dengan komentar:
public static boolean compare(final Object thisValue, final Object otherValue) {
boolean result;
if (thisValue == null) {
result = otherValue == null;
} else {
result = otherValue != null && thisValue.equals(otherValue); // questionable null check
}
return result;
}
Pemeriksaan tambahan di sini,, other != null
hanya diperlukan jika equals()
metode gagal memeriksa nol seperti yang dipersyaratkan dalam kontraknya.
Daripada berdebat tanpa hasil dengan kolega saya tentang kebijaksanaan membiarkan kode buggy tetap di basis kode kami, saya hanya menempatkan dua pernyataan dalam kode. Pernyataan ini akan memberi tahu saya, selama fase pengembangan, jika salah satu kelas kami gagal diimplementasikan equals()
dengan benar, jadi saya bisa memperbaikinya:
public static boolean compare(final Object thisValue, final Object otherValue) {
boolean result;
if (thisValue == null) {
result = otherValue == null;
assert otherValue == null || otherValue.equals(null) == false;
} else {
result = otherValue != null && thisValue.equals(otherValue);
assert thisValue.equals(null) == false;
}
return result;
}
Poin penting yang perlu diingat adalah ini:
Pernyataan adalah alat fase pengembangan saja.
Inti dari pernyataan ini adalah untuk memberi tahu Anda jika ada bug, tidak hanya di kode Anda, tetapi di basis kode Anda . (Pernyataan di sini sebenarnya akan menandai bug di kelas lain.)
Bahkan jika kolega saya yakin bahwa kelas kami ditulis dengan benar, pernyataan di sini masih akan berguna. Kelas-kelas baru akan ditambahkan yang mungkin gagal untuk menguji null, dan metode ini dapat menandai bug tersebut untuk kita.
Dalam pengembangan, Anda harus selalu mengaktifkan asersi, bahkan jika kode yang Anda tulis tidak menggunakan asersi. IDE saya diatur untuk selalu melakukan ini secara default untuk setiap executable baru.
Pernyataan tidak mengubah perilaku kode dalam produksi, jadi kolega saya senang bahwa cek nol ada di sana, dan bahwa metode ini akan dieksekusi dengan baik bahkan jika equals()
metode ini bermasalah. Saya senang karena saya akan menangkap equals()
metode kereta apa pun dalam pengembangan.
Juga, Anda harus menguji kebijakan pernyataan Anda dengan memasukkan pernyataan sementara yang akan gagal, sehingga Anda dapat yakin bahwa Anda diberitahu, baik melalui file log atau jejak tumpukan di aliran output.
Banyak jawaban bagus yang menjelaskan apa assert
kata kunci itu, tetapi hanya sedikit yang menjawab pertanyaan sebenarnya, "kapan assert
kata kunci itu digunakan dalam kehidupan nyata?"
Jawabannya: hampir tidak pernah .
Pernyataan, sebagai konsep, sangat bagus. Kode yang baik memiliki banyak if (...) throw ...
pernyataan (dan kerabat mereka suka Objects.requireNonNull
dan Math.addExact
). Namun, keputusan desain tertentu telah sangat membatasi kegunaan assert
kata kunci itu sendiri.
Gagasan penggerak di balik assert
kata kunci adalah pengoptimalan prematur, dan fitur utamanya adalah dapat dengan mudah mematikan semua cek. Bahkan, assert
pemeriksaan dimatikan secara default.
Namun, sangat penting bahwa pemeriksaan invarian terus dilakukan dalam produksi. Ini karena cakupan pengujian yang sempurna tidak mungkin, dan semua kode produksi akan memiliki bug yang pernyataannya harus membantu untuk mendiagnosis dan mengurangi.
Oleh karena itu, penggunaan if (...) throw ...
harus lebih disukai, seperti yang diperlukan untuk memeriksa nilai parameter metode publik dan untuk melempar IllegalArgumentException
.
Kadang-kadang, orang mungkin tergoda untuk menulis cek invarian yang membutuhkan waktu lama untuk diproses (dan sering disebut cukup untuk membuatnya penting). Namun, pemeriksaan semacam itu akan memperlambat pengujian yang juga tidak diinginkan. Pemeriksaan yang menghabiskan waktu seperti itu biasanya ditulis sebagai unit test. Namun demikian, kadang-kadang mungkin masuk akal untuk menggunakan assert
karena alasan ini.
Jangan gunakan assert
hanya karena lebih bersih dan lebih cantik dari if (...) throw ...
(dan saya katakan itu dengan sangat sakit, karena saya suka bersih dan cantik). Jika Anda tidak dapat membantu diri Anda sendiri, dan dapat mengontrol bagaimana aplikasi Anda diluncurkan, maka jangan ragu untuk menggunakannya assert
tetapi selalu aktifkan pernyataan dalam produksi. Harus diakui, inilah yang cenderung saya lakukan. Saya mendorong untuk anotasi lombok yang akan menyebabkan assert
bertindak lebih seperti if (...) throw ...
. Pilih di sini.
(Kata-kata kasar: para pengembang JVM adalah sekelompok pembuat kode yang mengerikan, yang mengoptimalkan secara prematur. Itulah mengapa Anda mendengar tentang begitu banyak masalah keamanan dalam plugin Java dan JVM. Mereka menolak untuk memasukkan pemeriksaan dasar dan pernyataan dalam kode produksi, dan kami terus melanjutkan bayar harganya.)
catch (Throwable t)
. Tidak ada alasan untuk tidak mencoba menjebak, mencatat, atau mencoba kembali / memulihkan dari OutOfMemoryError, AssertionError, dll.
assert
kata kunci yang buruk. Saya akan mengedit jawaban saya untuk membuatnya lebih jelas bahwa saya merujuk pada kata kunci, bukan konsepnya.
Inilah kasus penggunaan yang paling umum. Misalkan Anda mengaktifkan nilai enum:
switch (fruit) {
case apple:
// do something
break;
case pear:
// do something
break;
case banana:
// do something
break;
}
Selama Anda menangani setiap kasus, Anda baik-baik saja. Tetapi suatu hari, seseorang akan menambahkan ara ke enum Anda dan lupa untuk menambahkannya ke pernyataan pergantian Anda. Ini menghasilkan bug yang mungkin sulit ditangkap, karena efeknya tidak akan terasa sampai setelah Anda meninggalkan pernyataan pergantian. Tetapi jika Anda menulis pergantian Anda seperti ini, Anda dapat langsung menangkapnya:
switch (fruit) {
case apple:
// do something
break;
case pear:
// do something
break;
case banana:
// do something
break;
default:
assert false : "Missing enum value: " + fruit;
}
AssertionError
pernyataan if jika diaktifkan ( -ea
). Apa perilaku yang diinginkan dalam produksi? No-op sunyi dan potensi bencana nanti dalam eksekusi? Mungkin tidak. Saya akan menyarankan yang eksplisit throw new AssertionError("Missing enum value: " + fruit);
.
default
sehingga kompiler dapat memperingatkan Anda tentang kasus yang hilang. Anda bisa return
alih-alih break
(ini mungkin perlu mengekstraksi metode) dan kemudian menangani kasing yang hilang setelah sakelar. Dengan cara ini Anda mendapatkan peringatan dan peluang untuk melakukannya assert
.
Penegasan digunakan untuk memeriksa prakondisi dan kondisi "tidak boleh gagal". Kode yang benar seharusnya tidak pernah gagal dalam penegasan; ketika mereka memicu, mereka harus menunjukkan bug (mudah-mudahan di tempat yang dekat dengan tempat masalah sebenarnya).
Contoh pernyataan mungkin untuk memeriksa bahwa kelompok metode tertentu dipanggil dalam urutan yang benar (misalnya, yang hasNext()
disebut sebelumnya next()
dalam suatu Iterator
).
Apa kata kunci yang menegaskan di Jawa lakukan?
Mari kita lihat bytecode yang dikompilasi.
Kami akan menyimpulkan bahwa:
public class Assert {
public static void main(String[] args) {
assert System.currentTimeMillis() == 0L;
}
}
menghasilkan bytecode yang hampir sama persis seperti:
public class Assert {
static final boolean $assertionsDisabled =
!Assert.class.desiredAssertionStatus();
public static void main(String[] args) {
if (!$assertionsDisabled) {
if (System.currentTimeMillis() != 0L) {
throw new AssertionError();
}
}
}
}
di mana Assert.class.desiredAssertionStatus()
adalah true
ketika-ea
dilewatkan pada baris perintah, dan false jika tidak.
Kita gunakan System.currentTimeMillis()
untuk memastikan bahwa itu tidak akan dioptimalkan ( assert true;
lakukan).
Bidang sintetis dihasilkan sehingga Java hanya perlu memanggil Assert.class.desiredAssertionStatus()
satu kali pada waktu pengambilan, dan kemudian menyimpan hasilnya di sana. Lihat juga: Apa arti "sintetis sintetik"?
Kami dapat memverifikasi itu dengan:
javac Assert.java
javap -c -constants -private -verbose Assert.class
Dengan Oracle JDK 1.8.0_45, bidang statis sintetik dihasilkan (lihat juga: Apa arti dari "sintetis sintetik"? ):
static final boolean $assertionsDisabled;
descriptor: Z
flags: ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC
bersama dengan penginisialisasi statis:
0: ldc #6 // class Assert
2: invokevirtual #7 // Method java/lang Class.desiredAssertionStatus:()Z
5: ifne 12
8: iconst_1
9: goto 13
12: iconst_0
13: putstatic #2 // Field $assertionsDisabled:Z
16: return
dan metode utamanya adalah:
0: getstatic #2 // Field $assertionsDisabled:Z
3: ifne 22
6: invokestatic #3 // Method java/lang/System.currentTimeMillis:()J
9: lconst_0
10: lcmp
11: ifeq 22
14: new #4 // class java/lang/AssertionError
17: dup
18: invokespecial #5 // Method java/lang/AssertionError."<init>":()V
21: athrow
22: return
Kami menyimpulkan bahwa:
assert
: itu adalah konsep bahasa Jawaassert
dapat ditiru dengan baik dengan properti sistem -Pcom.me.assert=true
untuk menggantikan -ea
pada baris perintah, dan a throw new AssertionError()
.catch (Throwable t)
klausa juga bisa menangkap pelanggaran pernyataan? Bagi saya itu membatasi utilitas mereka hanya untuk kasus di mana tubuh pernyataan itu memakan waktu, yang jarang terjadi.
AssertionError
pertama dan menyusun kembali.
Contoh dunia nyata, dari kelas Stack (dari Assertion in Java Artikel )
public int pop() {
// precondition
assert !isEmpty() : "Stack is empty";
return stack[--num];
}
Pernyataan memungkinkan untuk mendeteksi cacat dalam kode. Anda dapat mengaktifkan pernyataan untuk pengujian dan debugging sambil membiarkannya ketika program Anda sedang dalam produksi.
Mengapa menegaskan sesuatu ketika Anda tahu itu benar? Hanya benar ketika semuanya bekerja dengan baik. Jika program memiliki cacat, itu mungkin sebenarnya tidak benar. Mendeteksi ini sebelumnya dalam proses membuat Anda tahu ada sesuatu yang salah.
Sebuah assert
pernyataan berisi pernyataan ini bersama dengan opsional String
pesan.
Sintaks untuk pernyataan tegas memiliki dua bentuk:
assert boolean_expression;
assert boolean_expression: error_message;
Berikut adalah beberapa aturan dasar yang mengatur di mana pernyataan harus digunakan dan di mana mereka seharusnya tidak digunakan. Pernyataan harus digunakan untuk:
Memvalidasi parameter input dari metode pribadi. BUKAN untuk metode publik. public
metode harus membuang pengecualian reguler ketika melewati parameter buruk.
Di mana saja dalam program untuk memastikan validitas fakta yang hampir pasti benar.
Misalnya, jika Anda yakin hanya 1 atau 2, Anda dapat menggunakan pernyataan seperti ini:
...
if (i == 1) {
...
}
else if (i == 2) {
...
} else {
assert false : "cannot happen. i is " + i;
}
...
Pernyataan tidak boleh digunakan untuk:
Memvalidasi parameter input dari metode publik. Karena pernyataan mungkin tidak selalu dieksekusi, mekanisme pengecualian reguler harus digunakan.
Memvalidasi kendala pada sesuatu yang diinput oleh pengguna. Sama seperti di atas.
Seharusnya tidak digunakan untuk efek samping.
Sebagai contoh, ini bukan penggunaan yang tepat karena di sini pernyataan digunakan untuk efek samping dari pemanggilan doSomething()
metode.
public boolean doSomething() {
...
}
public void someMethod() {
assert doSomething();
}
Satu-satunya kasus di mana ini dapat dibenarkan adalah ketika Anda mencoba mencari tahu apakah pernyataan diaktifkan atau tidak dalam kode Anda:
boolean enabled = false;
assert enabled = true;
if (enabled) {
System.out.println("Assertions are enabled");
} else {
System.out.println("Assertions are disabled");
}
Selain semua jawaban hebat yang diberikan di sini, panduan pemrograman Java SE 7 resmi memiliki manual yang cukup ringkas tentang penggunaan assert
; dengan beberapa contoh langsung ketika itu ide yang bagus (dan, yang penting, buruk) untuk menggunakan pernyataan, dan bagaimana hal itu berbeda dari melemparkan pengecualian.
Ketegasan sangat bermanfaat saat berkembang. Anda menggunakannya ketika sesuatu tidak bisa terjadi jika kode Anda bekerja dengan benar. Ini mudah digunakan, dan dapat tetap berada dalam kode untuk selamanya, karena akan dimatikan dalam kehidupan nyata.
Jika ada kemungkinan kondisi tersebut dapat terjadi dalam kehidupan nyata, maka Anda harus menanganinya.
Saya menyukainya, tetapi tidak tahu cara menyalakannya di Eclipse / Android / ADT. Tampaknya tidak aktif bahkan ketika debugging. (Ada utas tentang ini, tetapi merujuk pada 'Java vm', yang tidak muncul dalam Konfigurasi Jalankan ADT).
Berikut adalah pernyataan yang saya tulis di server untuk proyek Hibernate / SQL. Entitas kacang memiliki dua sifat boolean yang efektif, yang disebut isActive dan isDefault. Masing-masing dapat memiliki nilai "Y" atau "N" atau null, yang diperlakukan sebagai "N". Kami ingin memastikan klien browser dibatasi pada tiga nilai ini. Jadi, di setter saya untuk dua properti ini, saya menambahkan pernyataan ini:
assert new HashSet<String>(Arrays.asList("Y", "N", null)).contains(value) : value;
Perhatikan yang berikut ini.
Penegasan ini hanya untuk fase pengembangan. Jika klien mengirimkan nilai buruk, kami akan menangkapnya lebih awal dan memperbaikinya, jauh sebelum kami mencapai produksi. Pernyataan untuk cacat yang bisa Anda tangkap lebih awal.
Penegasan ini lambat dan tidak efisien. Tidak apa-apa. Pernyataan bebas untuk lambat. Kami tidak peduli karena mereka hanya alat pengembangan. Ini tidak akan memperlambat kode produksi karena pernyataan akan dinonaktifkan. (Ada beberapa ketidaksepakatan tentang hal ini, yang akan saya bahas nanti.) Ini mengarah ke poin saya berikutnya.
Pernyataan ini tidak memiliki efek samping. Saya bisa menguji nilai saya terhadap Set final statis yang tidak dapat dimodifikasi, tetapi set itu akan tetap ada dalam produksi, di mana ia tidak akan pernah digunakan.
Pernyataan ini ada untuk memverifikasi operasi klien yang tepat. Jadi pada saat kami mencapai produksi, kami akan yakin bahwa klien beroperasi dengan benar, sehingga kami dapat dengan aman mematikan pernyataan tersebut.
Beberapa orang bertanya ini: Jika pernyataan tidak diperlukan dalam produksi, mengapa tidak mengeluarkannya begitu selesai? Karena Anda masih akan membutuhkannya saat Anda mulai mengerjakan versi berikutnya.
Beberapa orang berpendapat bahwa Anda seharusnya tidak pernah menggunakan pernyataan, karena Anda tidak pernah bisa yakin bahwa semua bug telah hilang, jadi Anda perlu menjaga mereka di sekitar bahkan dalam produksi. Jadi tidak ada gunanya menggunakan pernyataan tegas, karena satu-satunya keuntungan untuk menegaskan adalah bahwa Anda dapat mematikannya. Karenanya, menurut pemikiran ini, Anda seharusnya (hampir) tidak pernah menggunakan penegasan. Saya tidak setuju. Memang benar bahwa jika sebuah tes termasuk dalam produksi, Anda tidak boleh menggunakan pernyataan. Tetapi tes ini tidak termasuk dalam produksi. Yang ini untuk menangkap bug yang kemungkinan besar tidak akan pernah mencapai produksi, sehingga dapat dimatikan dengan aman ketika Anda selesai.
BTW, saya bisa menulisnya seperti ini:
assert value == null || value.equals("Y") || value.equals("N") : value;
Ini bagus untuk hanya tiga nilai, tetapi jika jumlah nilai yang mungkin semakin besar, versi HashSet menjadi lebih nyaman. Saya memilih versi HashSet untuk menjelaskan efisiensi.
HashSet
membawa keunggulan kecepatan apa pun di atas ArrayList
. Selain itu, kreasi kumpulan dan daftar mendominasi waktu pencarian. Mereka akan baik-baik saja ketika menggunakan konstanta. Itu semua berkata, +1.
Pernyataan pada dasarnya digunakan untuk men-debug aplikasi atau digunakan sebagai pengganti penanganan pengecualian untuk beberapa aplikasi untuk memeriksa validitas aplikasi.
Penegasan bekerja pada saat dijalankan. Sebuah contoh sederhana, yang dapat menjelaskan keseluruhan konsep dengan sangat sederhana, ada di sini - Apa kata kunci tegas lakukan di Jawa?(WikiAnswers).
Pernyataan dinonaktifkan secara default. Untuk mengaktifkannya, kita harus menjalankan program dengan -ea
opsi (granularity dapat bervariasi). Sebagai contoh java -ea AssertionsDemo
,.
Ada dua format untuk menggunakan pernyataan:
assert 1==2; // This will raise an AssertionError
.assert 1==2: "no way.. 1 is not equal to 2";
Ini akan memunculkan AssertionError dengan pesan yang diberikan juga ditampilkan dan karenanya lebih baik. Meskipun sintaks sebenarnya adalah di assert expr1:expr2
mana expr2 dapat berupa ekspresi apa pun yang mengembalikan nilai, saya telah menggunakannya lebih sering hanya untuk mencetak pesan.Untuk rekap (dan ini berlaku untuk banyak bahasa bukan hanya Jawa):
"menegaskan" terutama digunakan sebagai bantuan debugging oleh pengembang perangkat lunak selama proses debugging. Pesan tegas seharusnya tidak pernah muncul. Banyak bahasa menyediakan opsi waktu kompilasi yang akan menyebabkan semua "menegaskan" diabaikan, untuk digunakan dalam menghasilkan kode "produksi".
"Pengecualian" adalah cara praktis untuk menangani semua jenis kondisi kesalahan, apakah itu merupakan kesalahan logika atau tidak, karena, jika Anda mengalami kondisi kesalahan sehingga Anda tidak dapat melanjutkan, Anda bisa "membuangnya ke udara," "Dari manapun Anda berada, mengharapkan orang lain di luar sana siap untuk" menangkap "mereka. Kontrol ditransfer dalam satu langkah, langsung dari kode yang melemparkan pengecualian, langsung ke sarung tangan penangkap. (Dan penangkap dapat melihat jejak balik lengkap dari panggilan yang telah terjadi.)
Lebih jauh, penelepon subrutin itu tidak perlu memeriksa untuk melihat apakah subrutin itu berhasil: "jika kita di sini sekarang, itu pasti berhasil, karena kalau tidak maka akan ada pengecualian dan kita tidak akan ada di sini sekarang!"Strategi sederhana ini membuat desain kode dan debugging menjadi jauh lebih mudah.
Pengecualian memungkinkan kondisi kesalahan fatal seperti apa adanya: "pengecualian terhadap aturan." Dan, bagi mereka untuk ditangani oleh jalur kode yang juga "pengecualian dari aturan ... " terbang bola! "
Penegasan adalah cek yang dapat dimatikan. Mereka jarang digunakan. Mengapa?
result != null
karena cek seperti itu sangat cepat dan hampir tidak ada yang bisa disimpan.Jadi, apa yang tersisa? Pemeriksaan mahal untuk kondisi benar-benar diharapkan menjadi kenyataan. Contoh yang baik adalah invarian dari struktur data seperti RB-tree. Sebenarnya, di ConcurrentHashMap
JDK8, ada beberapa pernyataan bermakna seperti untuk TreeNodes
.
Terkadang, ceknya tidak terlalu mahal, tetapi pada saat yang sama, Anda cukup yakin, itu akan berlalu. Dalam kode saya, ada misalnya,
assert Sets.newHashSet(userIds).size() == userIds.size();
di mana saya cukup yakin bahwa daftar yang baru saja saya buat memiliki elemen unik, tetapi saya ingin mendokumentasikan dan mengeceknya.
Pada dasarnya, "menegaskan benar" akan berlalu dan "menyatakan salah" akan gagal. Mari kita lihat bagaimana ini akan bekerja:
public static void main(String[] args)
{
String s1 = "Hello";
assert checkInteger(s1);
}
private static boolean checkInteger(String s)
{
try {
Integer.parseInt(s);
return true;
}
catch(Exception e)
{
return false;
}
}
assert
adalah kata kunci. Itu diperkenalkan di JDK 1.4. Ada dua jenis assert
s
assert
Pernyataan yang sangat sederhanaassert
Pernyataan sederhana .Secara default semua assert
pernyataan tidak akan dieksekusi. Jika sebuah assert
pernyataan menerima false, maka secara otomatis akan memunculkan kesalahan pernyataan.