Katakanlah saya memiliki antarmuka fungsional berikut di Java 8:
interface Action<T, U> {
U execute(T t);
}
Dan untuk beberapa kasus saya perlu tindakan tanpa argumen atau tipe pengembalian. Jadi saya menulis sesuatu seperti ini:
Action<Void, Void> a = () -> { System.out.println("Do nothing!"); };
Namun, itu memberi saya kesalahan kompilasi, saya harus menuliskannya sebagai
Action<Void, Void> a = (Void v) -> { System.out.println("Do nothing!"); return null;};
Itu jelek. Apakah ada cara untuk menghilangkan Void
parameter type?
Runnable
, yang Anda cariRunnable r = () -> System.out.println("Do nothing!");
Jawaban:
Sintaks yang Anda cari dimungkinkan dengan fungsi pembantu kecil yang mengubah a
Runnable
menjadiAction<Void, Void>
(misalnya, Anda dapat menempatkannyaAction
):sumber
@FunctionalInterface
. Dia hanya mengatakan, bahwa tidak mungkin untuk memperpanjangnya ...Runnable
tindakan harus mengambil@FunctionalInterface
sesuatu yang disebut kebiasaanSideEffect
, 2. kebutuhan untuk fungsi pembantu seperti itu menyoroti bahwa sesuatu yang aneh sedang terjadi dan mungkin abstraksi rusak.Gunakan
Supplier
jika tidak mengambil apa-apa, tetapi mengembalikan sesuatu.Gunakan
Consumer
jika dibutuhkan sesuatu, tetapi tidak menghasilkan apa-apa.Gunakan
Callable
jika itu mengembalikan hasil dan mungkin melempar (paling mirip denganThunk
istilah CS umum).Gunakan
Runnable
jika tidak dan tidak bisa melempar.sumber
public static void wrapCall(Runnable r) { r.run(); }
. Terima kasihLambda:
sebenarnya mewakili implementasi untuk antarmuka seperti:
yang sama sekali berbeda dari yang telah Anda tetapkan. Itu sebabnya Anda mendapatkan kesalahan.
Karena Anda tidak dapat memperpanjang
@FunctionalInterface
, atau memperkenalkan yang baru, maka saya pikir Anda tidak memiliki banyak pilihan. Anda dapat menggunakanOptional<T>
antarmuka untuk menunjukkan bahwa beberapa nilai (tipe kembali atau parameter metode) tidak ada. Namun, ini tidak akan membuat tubuh lambda lebih sederhana.sumber
Something
fungsi Anda tidak dapat menjadi subtipe dariAction
tipe saya , dan saya tidak dapat memiliki dua tipe yang berbeda.Anda dapat membuat sub-antarmuka untuk kasus khusus itu:
Ini menggunakan metode default untuk mengganti metode parameterisasi yang diwariskan
Void execute(Void)
, mendelegasikan panggilan ke metode yang lebih sederhanavoid execute()
.Hasilnya adalah lebih mudah digunakan:
sumber
Action<T, U>
dideklarasikan dalam pertanyaan .....Saya pikir tabel ini pendek dan bermanfaat:
Seperti yang dikatakan pada jawaban lain, opsi yang sesuai untuk masalah ini adalah a
Runnable
sumber
Itu tidak mungkin. Fungsi yang memiliki tipe pengembalian non-void (bahkan jika itu
Void
) harus mengembalikan nilai. Namun Anda dapat menambahkan metode statisAction
yang memungkinkan Anda untuk "membuat" aAction
:Itu akan memungkinkan Anda untuk menulis yang berikut:
sumber
Tambahkan metode statis di dalam antarmuka fungsional Anda
Keluaran
sumber
Saya tidak berpikir itu mungkin, karena definisi fungsi tidak cocok dalam contoh Anda.
Ekspresi lambda Anda dievaluasi persis seperti
sedangkan deklarasi Anda terlihat seperti
sebagai contoh, jika Anda memiliki antarmuka berikut
satu-satunya jenis fungsi (saat instantiating) yang akan kompatibel terlihat seperti
dan salah satu dari pernyataan atau argumen pengembalian akan memberi Anda kesalahan kompiler.
Oleh karena itu, jika Anda mendeklarasikan fungsi yang mengambil argumen dan mengembalikan satu, saya pikir tidak mungkin untuk mengubahnya menjadi fungsi yang tidak disebutkan di atas.
sumber
Hanya untuk referensi antarmuka fungsional yang dapat digunakan untuk referensi metode dalam kasus metode melempar dan / atau mengembalikan nilai.
sumber