Jenis Void di Java

1. Ikhtisar

Sebagai pengembang Java, kami mungkin pernah menemukan tipe Void di beberapa kesempatan dan bertanya-tanya apa tujuannya.

Dalam tutorial singkat ini, kita akan belajar tentang kelas khusus ini dan melihat kapan dan bagaimana menggunakannya serta bagaimana menghindari penggunaannya bila memungkinkan.

2. Apa Jenis Void itu

Sejak JDK 1.1, Java memberi kita tipe Void . Tujuannya hanyalah untuk mewakili tipe pengembalian kosong sebagai kelas dan berisi nilai publik Kelas . Ini tidak bisa dipakai karena satu-satunya konstruktornya adalah pribadi.

Oleh karena itu, satu-satunya nilai yang dapat kita tetapkan ke variabel Void adalah nol . Ini mungkin tampak sedikit tidak berguna, tetapi sekarang kita akan melihat kapan dan bagaimana menggunakan jenis ini.

3. Penggunaan

Ada beberapa situasi saat menggunakan tipe Void bisa jadi menarik.

3.1. Refleksi

Pertama, kita bisa menggunakannya saat melakukan refleksi. Memang, tipe kembalian dari metode void apa pun akan cocok dengan variabel Void.TYPE yang menyimpan nilai Kelas yang disebutkan sebelumnya .

Mari kita bayangkan kelas Kalkulator sederhana :

public class Calculator { private int result = 0; public int add(int number) { return result += number; } public int sub(int number) { return result -= number; } public void clear() { result = 0; } public void print() { System.out.println(result); } }

Beberapa metode mengembalikan integer, beberapa tidak mengembalikan apa pun. Sekarang, katakanlah kita harus mengambil, dengan refleksi, semua metode yang tidak mengembalikan hasil apa pun . Kami akan mencapai ini dengan menggunakan variabel Void.TYPE :

@Test void givenCalculator_whenGettingVoidMethodsByReflection_thenOnlyClearAndPrint() { Method[] calculatorMethods = Calculator.class.getDeclaredMethods(); List calculatorVoidMethods = Arrays.stream(calculatorMethods) .filter(method -> method.getReturnType().equals(Void.TYPE)) .collect(Collectors.toList()); assertThat(calculatorVoidMethods) .allMatch(method -> Arrays.asList("clear", "print").contains(method.getName())); }

Seperti yang bisa kita lihat, hanya metode clear () dan print () yang telah diambil.

3.2. Generik

Penggunaan lain dari tipe Void adalah dengan kelas generik. Misalkan kita memanggil metode yang membutuhkan parameter Callable :

public class Defer { public static  V defer(Callable callable) throws Exception { return callable.call(); } }

Namun, Callable yang ingin kami berikan tidak harus mengembalikan apa pun. Oleh karena itu, kami dapat memberikan Callable :

@Test void givenVoidCallable_whenDiffer_thenReturnNull() throws Exception { Callable callable = new Callable() { @Override public Void call() { System.out.println("Hello!"); return null; } }; assertThat(Defer.defer(callable)).isNull(); }

Kita bisa saja menggunakan tipe acak (misalnya Callable ) dan mengembalikan null atau tidak sama sekali ( Callable) , tetapi menggunakan Void menyatakan niat kita dengan jelas.

Kami juga dapat menerapkan metode ini ke lambda. Faktanya, Callable kami bisa saja ditulis sebagai lambda. Mari kita bayangkan sebuah metode yang membutuhkan sebuah Fungsi , tetapi kami ingin menggunakan sebuah Fungsi yang tidak mengembalikan apa pun. Maka kita hanya harus membuatnya mengembalikan Void :

public static  R defer(Function function, T arg) { return function.apply(arg); }
@Test void givenVoidFunction_whenDiffer_thenReturnNull() { Function function = s -> { System.out.println("Hello " + s + "!"); return null; }; assertThat(Defer.defer(function, "World")).isNull(); }

4. Bagaimana Menghindari Penggunaannya?

Sekarang, kita telah melihat beberapa penggunaan tipe Void . Namun, meskipun penggunaan pertama baik-baik saja, kami mungkin ingin menghindari penggunaan Void secara generik jika memungkinkan . Memang, menghadapi tipe kembalian yang merepresentasikan ketiadaan hasil dan hanya dapat berisi null bisa jadi merepotkan.

Sekarang kita akan melihat bagaimana menghindari situasi ini. Pertama, mari pertimbangkan metode kita dengan parameter Callable . Untuk menghindari penggunaan Callable , kami mungkin menawarkan metode lain yang mengambil parameter Runnable sebagai gantinya:

public static void defer(Runnable runnable) { runnable.run(); }

Jadi, kita bisa meneruskannya menjadi Runnable yang tidak mengembalikan nilai apa pun dan dengan demikian menyingkirkan null yang tidak berguna :

Runnable runnable = new Runnable() { @Override public void run() { System.out.println("Hello!"); } }; Defer.defer(runnable);

Tapi kemudian, bagaimana jika kelas Defer bukan milik kita untuk dimodifikasi? Kemudian kita dapat tetap menggunakan opsi Callable atau membuat kelas lain menggunakan Runnable dan menunda panggilan ke kelas Defer :

public class MyOwnDefer { public static void defer(Runnable runnable) throws Exception { Defer.defer(new Callable() { @Override public Void call() { runnable.run(); return null; } }); } }

Dengan melakukan itu, kami merangkum bagian yang rumit sekali dan untuk semua dalam metode kami sendiri, memungkinkan pengembang di masa mendatang untuk menggunakan API yang lebih sederhana.

Tentu saja, hal yang sama bisa dicapai untuk Function . Dalam contoh kami, Fungsi tidak mengembalikan apa pun, sehingga kami dapat menyediakan metode lain yang mengambil Konsumen sebagai gantinya:

public static  void defer(Consumer consumer, T arg) { consumer.accept(arg); }

Lalu, bagaimana jika fungsi kita tidak mengambil parameter apa pun? Kita dapat menggunakan Runnable atau membuat antarmuka fungsional kita sendiri (jika itu tampak lebih jelas):

public interface Action { void execute(); }

Kemudian, kami membebani lagi metode defer () :

public static void defer(Action action) { action.execute(); }
Action action = () -> System.out.println("Hello!"); Defer.defer(action);

5. Kesimpulan

Dalam artikel singkat ini, kami membahas kelas Java Void . Kami melihat apa tujuannya dan bagaimana menggunakannya. Kami juga mempelajari beberapa alternatif untuk penggunaannya.

Seperti biasa, kode lengkap artikel ini dapat ditemukan di GitHub kami.