Saya memiliki kebutuhan untuk "Runnable yang menerima parameter" walaupun saya tahu bahwa runnable tidak benar-benar ada.
Ini mungkin menunjukkan kelemahan mendasar dalam desain aplikasi saya dan / atau blok mental di otak saya yang lelah, jadi saya berharap untuk menemukan beberapa saran di sini tentang cara mencapai sesuatu seperti berikut, tanpa melanggar prinsip-prinsip OO mendasar:
private Runnable mOneShotTask = new Runnable(String str) {
public void run(String str) {
someFunc(str);
}
};
Adakah cara untuk mencapai sesuatu seperti di atas?
Consumer<T>
.Consumer<T>
Jawaban:
Sudah hampir 9 tahun sejak saya memposting ini dan sejujurnya, Java telah membuat beberapa perbaikan sejak itu. Saya akan meninggalkan jawaban asli saya di bawah, tetapi tidak perlu bagi orang untuk melakukan apa yang ada di dalamnya. 9 tahun yang lalu, selama tinjauan kode saya akan mempertanyakan mengapa mereka melakukannya dan mungkin menyetujuinya, mungkin tidak. Dengan lambda modern tersedia, itu tidak bertanggung jawab untuk memiliki jawaban yang sangat tinggi merekomendasikan pendekatan kuno (yang, pada semua keadilan, meragukan untuk memulai dengan ...) Di Jawa modern, bahwa tinjauan kode akan segera ditolak, dan ini akan menjadi menyarankan:
Seperti sebelumnya, detail seperti menangani utas itu dengan cara yang bermanfaat dibiarkan sebagai latihan bagi pembaca. Tapi terus terang, jika Anda takut menggunakan lambdas, Anda harus lebih takut dengan sistem multi-threaded.
Jawaban asli, hanya karena:
Anda bisa mendeklarasikan kelas tepat di metode
sumber
Anda bisa memasukkannya ke dalam fungsi.
(Ketika saya menggunakan ini, parameter saya adalah ID integer, yang saya gunakan untuk membuat hashmap ID -> myRunnables. Dengan begitu, saya bisa menggunakan hashmap untuk memposting / menghapus objek myRunnable yang berbeda di dalam handler.)
sumber
Runnable
objek yang dikembalikan oleh metode ada di mana saja,paramStr
mungkin tidak akan memenuhi syarat untuk pengumpulan sampah. Ada kemungkinan bahwa jika objek ada tetapi tidak pernah dapat dijalankan lagi, JIT (atau bahkan javac) dapat memutuskan untuk menghapusnya dari ruang lingkup, tetapi kita tidak boleh mengandalkan optimisasi tersebut karena mereka dapat berubah di masa depan.Buat fungsi init yang mengembalikan objek itu sendiri dan menginisialisasi parameter dengannya.
sumber
Saya menggunakan kelas berikut yang mengimplementasikan antarmuka Runnable . Dengan kelas ini Anda dapat dengan mudah membuat utas baru dengan argumen
sumber
public RunnableArg(Object... args) { setArgs(args); }
kemudian menggambarkan kelas lokal:class ActionArg extends RunnableArg { public ActionArg(Object... arg) { super(arg); } @Override public void run() { /* getArgs() and process them */ } }
dan menggunakannyaThread t = new Thread(new ActionArg( %param_object(s)% )); t.start();
Anda memiliki dua opsi:
Tentukan kelas bernama. Lewati parameter Anda ke konstruktor dari kelas bernama.
Biarkan kelas anonim Anda menutup "parameter" Anda. Pastikan untuk menandainya sebagai
final
.sumber
Sejak Java 8, jawaban terbaik adalah menggunakan
Consumer<T>
:https://docs.oracle.com/javase/8/docs/api/java/util/function/Consumer.html
Ini adalah salah satu antarmuka fungsional, yang berarti Anda dapat menyebutnya sebagai ekspresi lambda:
sumber
Pertama-tama saya ingin tahu apa yang ingin Anda capai di sini sehingga perlu argumen untuk diteruskan ke Runnable baru () atau untuk menjalankan (). Cara biasa seharusnya memiliki objek Runnable yang meneruskan data (str) ke utasnya dengan mengatur variabel anggota sebelum memulai. Metode run () kemudian menggunakan nilai-nilai variabel anggota ini untuk melakukan eksekusi someFunc ()
sumber