Cara menggunakan pernyataan di Java

Menulis program yang bekerja dengan benar saat runtime dapat menjadi tantangan. Ini karena asumsi kami tentang bagaimana kode kami akan berperilaku ketika dijalankan sering salah. Menggunakan fitur pernyataan Java adalah salah satu cara untuk memverifikasi bahwa logika pemrograman Anda benar.

Tutorial ini memperkenalkan pernyataan Java. Pertama-tama Anda akan mempelajari apa yang dimaksud dengan pernyataan dan cara menentukan serta menggunakannya dalam kode Anda. Selanjutnya, Anda akan menemukan cara menggunakan pernyataan untuk memberlakukan prasyarat dan pascakondisi. Terakhir, Anda akan membandingkan pernyataan dengan pengecualian, dan mencari tahu mengapa Anda membutuhkan keduanya dalam kode Anda.

unduh Dapatkan kodenya Unduh kode sumber untuk contoh dalam tutorial ini. Dibuat oleh Jeff Friesen untuk JavaWorld.

Apa itu pernyataan Java?

Sebelum JDK 1.4, pengembang sering menggunakan komentar untuk mendokumentasikan asumsi tentang kebenaran program. Namun, komentar tidak berguna sebagai mekanisme untuk menguji dan men-debug asumsi. Kompilator mengabaikan komentar, jadi tidak ada cara untuk menggunakannya untuk deteksi bug. Pengembang juga sering tidak memperbarui komentar saat mengubah kode.  

Di JDK 1.4, pernyataan diperkenalkan sebagai mekanisme baru untuk menguji dan men-debug asumsi tentang kode kami. Intinya, pernyataan  adalah entitas yang dapat dikompilasi yang dijalankan pada waktu proses, dengan asumsi Anda telah mengaktifkannya untuk pengujian program. Anda dapat memprogram pernyataan untuk memberi tahu Anda tentang bug di mana bug itu terjadi, sangat mengurangi jumlah waktu yang seharusnya Anda habiskan untuk men-debug program yang gagal.

Pernyataan digunakan untuk menyusun persyaratan yang membuat program benar atau tidak dengan kondisi pengujian (ekspresi Boolean) untuk nilai sebenarnya, dan memberi tahu pengembang jika kondisi tersebut salah. Menggunakan pernyataan dapat sangat meningkatkan kepercayaan Anda pada kebenaran kode Anda.

Cara menulis pernyataan di Java

Pernyataan diimplementasikan melalui assertpernyataan dan java.lang.AssertionErrorkelas. Pernyataan ini dimulai dengan kata kunci assertdan dilanjutkan dengan ekspresi Boolean. Ini diungkapkan secara sintaksis sebagai berikut:

menegaskan BooleanExpr ;

Jika BooleanExprdievaluasi ke true, tidak ada yang terjadi dan eksekusi dilanjutkan. Jika ekspresi bernilai false, bagaimanapun, AssertionErrordibuat instance-nya dan dilempar, seperti yang ditunjukkan dalam Listing 1.

Daftar 1:AssertDemo.java (versi 1)

kelas publik AssertDemo {public static void main (String [] args) {int x = -1; tegaskan x> = 0; }}

Penegasan dalam Daftar 1 menunjukkan keyakinan pengembang bahwa variabel xmengandung nilai yang lebih besar dari atau sama dengan 0. Namun, ini jelas bukan masalahnya; yang asserthasil eksekusi pernyataan dalam sebuah dilemparkan AssertionError.

Kompilasi Listing 1 ( javac AssertDemo.java) dan jalankan dengan assertions enabled ( java -ea AssertDemo). Anda harus mengamati keluaran berikut:

Pengecualian di thread "main" java.lang.AssertionError di AssertDemo.main (AssertDemo.java:6)

Pesan ini agak samar karena tidak mengidentifikasi apa yang menyebabkan AssertionErrordilempar. Jika Anda menginginkan pesan yang lebih informatif, gunakan assertpernyataan di bawah ini:

menegaskan BooleanExpr : expr ;

Di sini, expradalah ekspresi apa pun (termasuk pemanggilan metode) yang bisa mengembalikan nilai - Anda tidak bisa memanggil metode dengan voidtipe kembalian. Ekspresi yang berguna adalah string literal yang menjelaskan alasan kegagalan, seperti yang ditunjukkan pada Kode 2.

Daftar 2:AssertDemo.java (versi 2)

kelas publik AssertDemo {public static void main (String [] args) {int x = -1; tegaskan x> = 0: "x <0"; }}

Kompilasi Listing 2 ( javac AssertDemo.java) dan jalankan dengan assertions enabled ( java -ea AssertDemo). Kali ini, Anda harus mengamati keluaran yang sedikit diperluas berikut, yang mencakup alasan munculnya AssertionError:

Pengecualian dalam utas "main" java.lang.AssertionError: x <0 di AssertDemo.main (AssertDemo.java:6)

Untuk salah satu contoh, menjalankan AssertDemotanpa opsi -ea(aktifkan pernyataan) tidak menghasilkan keluaran. Jika pernyataan tidak diaktifkan, pernyataan tersebut tidak akan dijalankan, meskipun pernyataan tersebut masih ada di file kelas.

Prekondisi dan pascakondisi

Assertions menguji asumsi program dengan memverifikasi bahwa berbagai prasyarat dan pascakondisinya tidak dilanggar, memberi tahu pengembang saat terjadi pelanggaran:

  • Sebuah prasyarat adalah suatu kondisi yang harus mengevaluasi dengan benar sebelum pelaksanaan beberapa urutan kode. Prasyarat memastikan bahwa penelepon menjaga kontrak mereka dengan calon pelanggan.
  • Sebuah postcondition adalah suatu kondisi yang harus mengevaluasi dengan benar setelah pelaksanaan beberapa urutan kode. Kondisi pos memastikan bahwa calon pelanggan menjaga kontrak mereka dengan penelepon.

Prasyarat

Anda dapat menerapkan prasyarat pada konstruktor dan metode publik dengan melakukan pemeriksaan eksplisit dan memberikan pengecualian jika diperlukan. Untuk metode pembantu pribadi, Anda bisa menerapkan prasyarat dengan menentukan pernyataan. Pertimbangkan Listing 3.

Daftar 3:AssertDemo.java (versi 3)

impor java.io.FileInputStream; impor java.io.InputStream; impor java.io.IOException; class PNG {/ ** * Buat instance PNG, baca file PNG yang ditentukan, dan dekode * ke dalam struktur yang sesuai. * * @param filespec jalur dan nama file PNG untuk dibaca * * @throws NullPointerException saat filespec*null* / PNG (String filespec) menampilkan IOException {// Berlakukan prasyarat dalam metode konstruktor dan // non-pribadi. if (filespec == null) melempar NullPointerException baru ("filespec is null"); coba (FileInputStream fis = FileInputStream baru (filespec)) {readHeader (fis); }} private void readHeader (InputStream is) melempar IOException {// Konfirmasi bahwa prasyarat terpenuhi dalam metode private // helper. menegaskan adalah! = null: "null diteruskan ke adalah"; }} kelas publik AssertDemo {public static void main (String [] args) melempar IOException {PNG png = new PNG ((args.length == 0)? null: args [0]); }}

The PNGkelas Listing 3 adalah awal minimal perpustakaan untuk membaca dan decoding PNG (grafis jaringan portable) file gambar. Konstruktor secara eksplisit membandingkan filespecdengan null, melempar NullPointerExceptionketika parameter ini berisi null. Intinya adalah untuk menegakkan prasyarat yang filespectidak mengandung null.

Ini tidak tepat untuk ditentukan assert filespec != null;karena prasyarat yang disebutkan dalam Javadoc konstruktor tidak akan (secara teknis) diberlakukan saat pernyataan dinonaktifkan. (Sebenarnya, itu akan dihormati karena FileInputStream()akan melempar NullPointerException, tetapi Anda tidak boleh bergantung pada perilaku yang tidak berdokumen.)

Namun, assertsesuai dalam konteks readHeader()metode pembantu pribadi , yang pada akhirnya akan diselesaikan untuk membaca dan mendekode header 8-byte file PNG. Prasyarat yang isselalu diteruskan nilai bukan nol akan selalu berlaku.

Kondisi pasca

Kondisi akhir biasanya ditentukan melalui pernyataan, terlepas dari apakah metode (atau konstruktor) bersifat publik atau tidak. Pertimbangkan Listing 4.

Daftar 4:AssertDemo.java (versi 4)

public class AssertDemo { public static void main(String[] args) { int[] array = { 20, 91, -6, 16, 0, 7, 51, 42, 3, 1 }; sort(array); for (int element: array) System.out.printf("%d ", element); System.out.println(); } private static boolean isSorted(int[] x) { for (int i = 0; i  x[i + 1]) return false; return true; } private static void sort(int[] x) { int j, a; // For all integer values except the leftmost value ... for (int i = 1; i  0 && x[j - 1] > a) { // Shift left value -- x[j - 1] -- one position to its right -- // x[j]. x[j] = x[j - 1]; // Update insert position to shifted value's original position // (one position to the left). j--; } // Insert a at insert position (which is either the initial insert // position or the final insert position), where a is greater than // or equal to all values to its left. x[j] = a; } assert isSorted(x): "array not sorted"; } }

Listing 4 presents a sort() helper method that uses the insertion sort algorithm to sort an array of integer values. I’ve used assert to check the postcondition of x being sorted before sort() returns to its caller.

The example in Listing 4 demonstrates an important characteristic of assertions, which is that they’re typically expensive to execute. For this reason, assertions are usually disabled in production code. In Listing 4, isSorted() must scan through the entire array, which can be time-consuming in the case of a lengthy array.

Assertions vs. exceptions in Java

Developers use assertions to document logically impossible situations and detect errors in their programming logic. At runtime, an enabled assertion alerts a developer to a logic error. The developer refactors the source code to fix the logic error and then recompiles this code.

Developers use Java’s exception mechanism to respond to non-fatal (e.g., running out of memory) runtime errors, which may be caused by environmental factors, such as a file not existing, or by poorly written code, such as an attempt to divide by 0. An exception handler is often written to gracefully recover from the error so that the program can continue to run.

Assertions are no substitute for exceptions. Unlike exceptions, assertions don’t support error recovery (assertions typically halt program execution immediately — AssertionError isn’t meant to be caught); they are often disabled in production code; and they typically don’t display user-friendly error messages (although this isn’t an issue with assert). It’s important to know when to use exceptions rather than assertions.

When to use exceptions

Suppose you’ve written a sqrt() method that calculates the square root of its argument. In a non-complex number context, it’s impossible to take the square root of a negative number. Therefore, you use an assertion to fail the method if the argument is negative. Consider the following code fragment:

public double sqrt(double x) { assert x >= 0 : "x is negative"; // ... }

It’s inappropriate to use an assertion to validate an argument in this public method. An assertion is intended to detect errors in programming logic and not to safeguard a method from erroneous arguments. Besides, if assertions are disabled, there is no way to deal with the problem of a negative argument. It’s better to throw an exception, as follows:

public double sqrt(double x) { if (x < 0) throw new IllegalArgumentException("x is negative"); // ... }

The developer might choose to have the program handle the illegal argument exception, or simply propagate it out of the program where an error message is displayed by the tool that runs the program. Upon reading the error message, the developer can fix whatever code led to the exception.

Anda mungkin telah memperhatikan perbedaan halus antara pernyataan dan logika deteksi kesalahan. Pengujian pernyataan x >= 0, sedangkan logika deteksi kesalahan menguji x < 0. Penegasannya optimis: Kami berasumsi bahwa argumennya OK. Sebaliknya, logika pendeteksian kesalahan bersifat pesimis: Kami menganggap bahwa argumennya tidak OK. Pernyataan mendokumentasikan logika yang benar, sedangkan pengecualian mendokumentasikan perilaku waktu proses yang salah.

Dalam tutorial ini Anda telah mempelajari cara menggunakan pernyataan untuk mendokumentasikan logika program yang benar. Anda juga telah mempelajari mengapa pernyataan bukanlah pengganti pengecualian, dan Anda telah melihat contoh di mana menggunakan pengecualian akan lebih efektif.

Artikel, "Bagaimana menggunakan pernyataan di Java" ini awalnya diterbitkan oleh JavaWorld.