Metode Java Pass sebagai Parameter

278

Saya mencari cara untuk lulus metode dengan referensi. Saya mengerti bahwa Java tidak lulus metode sebagai parameter, namun, saya ingin mendapatkan alternatif.

Saya telah diberitahu bahwa antarmuka adalah alternatif untuk melewati metode sebagai parameter, tetapi saya tidak mengerti bagaimana antarmuka dapat bertindak sebagai metode dengan referensi. Jika saya mengerti benar suatu antarmuka hanyalah seperangkat metode abstrak yang tidak didefinisikan. Saya tidak ingin mengirim antarmuka yang perlu didefinisikan setiap saat karena beberapa metode berbeda dapat memanggil metode yang sama dengan parameter yang sama.

Apa yang ingin saya capai adalah sesuatu yang mirip dengan ini:

public void setAllComponents(Component[] myComponentArray, Method myMethod) {
    for (Component leaf : myComponentArray) {
        if (leaf instanceof Container) { //recursive call if Container
            Container node = (Container) leaf;
            setAllComponents(node.getComponents(), myMethod);
        } //end if node
        myMethod(leaf);
    } //end looping through components
}

dipanggil seperti:

setAllComponents(this.getComponents(), changeColor());
setAllComponents(this.getComponents(), changeSize());
Yojimbo
sumber
sekarang solusi saya adalah untuk melewati parameter tambahan dan menggunakan sakelar di dalam untuk memilih metode yang sesuai. Namun, solusi ini tidak meminjamkan sementara untuk menggunakan kembali kode.
Lihat juga jawaban ini stackoverflow.com/a/22933032/1010868 untuk pertanyaan serupa
Tomasz Gawel

Jawaban:

233

Sunting : pada Java 8, ekspresi lambda adalah solusi yang bagus seperti yang ditunjukkan oleh jawaban lain . Jawaban di bawah ini ditulis untuk Java 7 dan sebelumnya ...


Lihatlah pola perintah .

// NOTE: code not tested, but I believe this is valid java...
public class CommandExample 
{
    public interface Command 
    {
        public void execute(Object data);
    }

    public class PrintCommand implements Command 
    {
        public void execute(Object data) 
        {
            System.out.println(data.toString());
        }    
    }

    public static void callCommand(Command command, Object data) 
    {
        command.execute(data);
    }

    public static void main(String... args) 
    {
        callCommand(new PrintCommand(), "hello world");
    }
}

Sunting: seperti yang ditunjukkan Pete Kirkham , ada cara lain untuk melakukan ini menggunakan Pengunjung . Pendekatan pengunjung sedikit lebih terlibat - simpul Anda semua harus sadar pengunjung dengan suatu acceptVisitor()metode - tetapi jika Anda perlu menelusuri grafik objek yang lebih kompleks maka perlu diperiksa.

Dan Vinton
sumber
2
@ Mac - bagus! ini muncul berulang-ulang dalam bahasa tanpa metode kelas satu sebagai cara de-facto untuk mensimulasikan mereka, jadi patut diingat.
Dan Vinton
7
Ini adalah pola pengunjung (pisahkan tindakan pengulangan atas koleksi dari fungsi yang diterapkan ke masing-masing anggota koleksi), bukan pola perintah (merangkum argumen untuk pemanggilan metode ke objek). Anda secara khusus tidak merangkum argumen - ini disediakan oleh bagian iterasi dari pola pengunjung.
Pete Kirkham
Tidak, Anda hanya perlu metode penerimaan jika Anda menggabungkan kunjungan dengan pengiriman ganda. Jika Anda memiliki pengunjung monomorfik, itu persis kode yang Anda miliki di atas.
Pete Kirkham
Di Java 8 bisa seperti ex.operS (String :: toLowerCase, "STRING"). Lihat artikel yang bagus: studytrails.com/java/java8/…
Zon
Pete Kirkham benar: kode Anda menerapkan pola Pengunjung, bukan pola Komando (dan ini bagus, seperti yang dibutuhkan OP). Seperti kata Pete, Anda tidak merangkum argumen, jadi Anda tidak melakukan Command - Command Anda antarmuka memiliki eksekusi yang mengambil parameter. Wikipedia tidak. Ini adalah dasar dari maksud pola Komando. Seperti paragraf pertama mengatakan "merangkum semua informasi ... Informasi ini termasuk nama metode, objek yang memiliki metode dan nilai-nilai untuk parameter metode ."
ToolmakerSteve
73

Di Java 8, Anda sekarang dapat melewati metode lebih mudah menggunakan Ekspresi Lambda dan Referensi Metode. Pertama, beberapa latar belakang: antarmuka fungsional adalah antarmuka yang memiliki satu dan hanya satu metode abstrak, meskipun dapat berisi sejumlah metode default (baru di Java 8) dan metode statis. Ekspresi lambda dapat dengan cepat mengimplementasikan metode abstrak, tanpa semua sintaks yang tidak perlu diperlukan jika Anda tidak menggunakan ekspresi lambda.

Tanpa ekspresi lambda:

obj.aMethod(new AFunctionalInterface() {
    @Override
    public boolean anotherMethod(int i)
    {
        return i == 982
    }
});

Dengan ekspresi lambda:

obj.aMethod(i -> i == 982);

Berikut adalah kutipan dari tutorial Java tentang Ekspresi Lambda :

Sintaksis Ekspresi Lambda

Ekspresi lambda terdiri dari yang berikut:

  • Daftar parameter formal yang dipisahkan koma, terlampir dalam tanda kurung. Metode CheckPerson.test berisi satu parameter, p, yang mewakili turunan dari kelas Person.

    Catatan : Anda bisa menghilangkan tipe data dari parameter dalam ekspresi lambda. Selain itu, Anda dapat menghilangkan tanda kurung jika hanya ada satu parameter. Misalnya, ekspresi lambda berikut ini juga valid:

    p -> p.getGender() == Person.Sex.MALE 
        && p.getAge() >= 18
        && p.getAge() <= 25
  • Tanda panah, ->

  • Badan, yang terdiri dari satu ekspresi atau blok pernyataan. Contoh ini menggunakan ungkapan berikut:

    p.getGender() == Person.Sex.MALE 
        && p.getAge() >= 18
        && p.getAge() <= 25

    Jika Anda menentukan satu ekspresi, maka Java runtime mengevaluasi ekspresi dan kemudian mengembalikan nilainya. Atau, Anda dapat menggunakan pernyataan kembali:

    p -> {
        return p.getGender() == Person.Sex.MALE
            && p.getAge() >= 18
            && p.getAge() <= 25;
    }

    Pernyataan pengembalian bukan ekspresi; dalam ekspresi lambda, Anda harus menyertakan pernyataan dalam kurung ({}). Namun, Anda tidak harus menyertakan permohonan metode void di kawat gigi. Misalnya, berikut ini adalah ekspresi lambda yang valid:

    email -> System.out.println(email)

Perhatikan bahwa ekspresi lambda sangat mirip dengan deklarasi metode; Anda dapat menganggap ekspresi lambda sebagai metode anonim — metode tanpa nama.


Inilah cara Anda dapat "meneruskan metode" menggunakan ekspresi lambda:

interface I {
    public void myMethod(Component component);
}

class A {
    public void changeColor(Component component) {
        // code here
    }

    public void changeSize(Component component) {
        // code here
    }
}
class B {
    public void setAllComponents(Component[] myComponentArray, I myMethodsInterface) {
        for(Component leaf : myComponentArray) {
            if(leaf instanceof Container) { // recursive call if Container
                Container node = (Container)leaf;
                setAllComponents(node.getComponents(), myMethodInterface);
            } // end if node
            myMethodsInterface.myMethod(leaf);
        } // end looping through components
    }
}
class C {
    A a = new A();
    B b = new B();

    public C() {
        b.setAllComponents(this.getComponents(), component -> a.changeColor(component));
        b.setAllComponents(this.getComponents(), component -> a.changeSize(component));
    }
}

Kelas Cdapat dipersingkat bahkan sedikit lebih jauh dengan menggunakan referensi metode seperti:

class C {
    A a = new A();
    B b = new B();

    public C() {
        b.setAllComponents(this.getComponents(), a::changeColor);
        b.setAllComponents(this.getComponents(), a::changeSize);
    }
}
The Guy with The Hat
sumber
Apakah kelas A perlu diwarisi dari antarmuka?
Serob_b
1
@Serob_b Tidak. Kecuali jika Anda ingin meneruskannya sebagai referensi metode (lihat ::operator), tidak masalah apa A. a.changeThing(component)dapat diubah ke pernyataan atau blok kode apa pun yang Anda inginkan, asalkan mengembalikan batal.
The Guy with The Hat
29

Gunakan java.lang.reflect.Methodobjek dan panggilinvoke

Vinodh Ramasubramanian
sumber
12
Saya tidak mengerti mengapa tidak. Pertanyaannya adalah untuk lulus metode sebagai parameter dan ini cara yang sangat valid untuk melakukannya. Ini juga dapat dibungkus dengan sejumlah pola cantik untuk membuatnya terlihat bagus. Dan ini generik karena tanpa perlu antarmuka khusus.
Vinodh Ramasubramanian
3
Sudahkah Anda mengetikkan keamanan dalam JavaScript fg? Jenis keamanan bukan argumen.
Danubian Sailor
13
Bagaimana jenis keamanan bukan argumen ketika bahasa yang dipermasalahkan mempertahankan keamanan jenis sebagai salah satu komponen terkuat? Java adalah bahasa yang sangat diketik, dan bahwa pengetikan yang kuat adalah salah satu alasan Anda memilihnya dari bahasa lain yang dikompilasi.
Adam Parkin
21
"Fasilitas refleksi inti pada awalnya dirancang untuk alat pembuat aplikasi berbasis komponen. [...] Sebagai aturan, objek tidak boleh diakses secara reflektif dalam aplikasi normal saat runtime." Butir 53: Memilih antarmuka untuk refleksi, dari Effective Java Second Edition. - Itulah garis pemikiran para pencipta Jawa ;-)
Wilhem Meignan
8
Bukan penggunaan refleksi yang dibenarkan. Saya ngeri melihat semua upvotes. mencerminkan tidak pernah dimaksudkan untuk digunakan sebagai mekanisme pemrograman umum; hanya gunakan saat tidak ada solusi bersih lainnya.
ToolmakerSteve
22

Karena Java 8 ada Function<T, R>antarmuka ( docs ), yang memiliki metode

R apply(T t);

Anda dapat menggunakannya untuk meneruskan fungsi sebagai parameter ke fungsi lainnya. T adalah tipe input dari fungsi, R adalah tipe kembali.

Dalam contoh Anda, Anda harus melewati fungsi yang mengambil Componenttipe sebagai input dan tidak mengembalikan apa pun - Void. Dalam hal Function<T, R>ini bukan pilihan terbaik, karena tidak ada autoboxing tipe Void. Antarmuka yang Anda cari disebut Consumer<T>( docs ) dengan metode

void accept(T t);

Akan terlihat seperti ini:

public void setAllComponents(Component[] myComponentArray, Consumer<Component> myMethod) {
    for (Component leaf : myComponentArray) {
        if (leaf instanceof Container) { 
            Container node = (Container) leaf;
            setAllComponents(node.getComponents(), myMethod);
        } 
        myMethod.accept(leaf);
    } 
}

Dan Anda akan menyebutnya menggunakan referensi metode:

setAllComponents(this.getComponents(), this::changeColor);
setAllComponents(this.getComponents(), this::changeSize); 

Dengan asumsi bahwa Anda telah mendefinisikan metode changeColor () dan changeSize () di kelas yang sama.


Jika metode Anda menerima lebih dari satu parameter, Anda dapat menggunakan BiFunction<T, U, R>- T dan U sebagai tipe parameter input dan R sebagai tipe pengembalian. Ada juga BiConsumer<T, U>(dua argumen, tidak ada tipe pengembalian). Sayangnya untuk 3 dan lebih banyak parameter input, Anda harus membuat antarmuka sendiri. Sebagai contoh:

public interface Function4<A, B, C, D, R> {

    R apply(A a, B b, C c, D d);
}
JakubM
sumber
19

Pertama tentukan Antarmuka dengan metode yang ingin Anda lewati sebagai parameter

public interface Callable {
  public void call(int param);
}

Menerapkan kelas dengan metode ini

class Test implements Callable {
  public void call(int param) {
    System.out.println( param );
  }
}

// Ajukan seperti itu

Callable cmd = new Test();

Ini memungkinkan Anda untuk melewatkan cmd sebagai parameter dan memanggil pemanggilan metode yang didefinisikan dalam antarmuka

public invoke( Callable callable ) {
  callable.call( 5 );
}
stacker
sumber
1
Anda mungkin tidak perlu membuat antarmuka sendiri karena java telah mendefinisikan banyak untuk Anda: docs.oracle.com/javase/8/docs/api/java/util/function/…
slim
@slim Poin menarik, seberapa stabil definisi-definisi itu, apakah definisi itu dimaksudkan untuk digunakan secara khusus seperti yang Anda sarankan, atau apakah mungkin akan pecah?
Manuel
@slim Sebenarnya, dokumen menjawab bahwa: "Antarmuka dalam paket ini adalah antarmuka fungsional tujuan umum yang digunakan oleh JDK, dan tersedia untuk digunakan oleh kode pengguna juga."
Manuel
14

Meskipun ini belum berlaku untuk Java 7 dan di bawah, saya percaya bahwa kita harus melihat ke masa depan dan setidaknya mengenali perubahan yang akan terjadi dalam versi baru seperti Java 8.

Yaitu, versi baru ini membawa lambdas dan referensi metode ke Jawa (bersama dengan API baru , yang merupakan solusi lain yang valid untuk masalah ini. Meskipun mereka masih memerlukan antarmuka, tidak ada objek baru yang dibuat, dan file class tambahan tidak perlu mencemari direktori keluaran karena perbedaan penanganan oleh JVM.

Kedua rasa (lambda dan referensi metode) memerlukan antarmuka yang tersedia dengan metode tunggal yang tanda tangannya digunakan:

public interface NewVersionTest{
    String returnAString(Object oIn, String str);
}

Nama metode tidak akan menjadi masalah mulai saat ini. Di mana lambda diterima, referensi metode juga. Misalnya, untuk menggunakan tanda tangan kami di sini:

public static void printOutput(NewVersionTest t, Object o, String s){
    System.out.println(t.returnAString(o, s));
}

Ini hanya permohonan antarmuka yang sederhana, hingga lambda 1 dilewati:

public static void main(String[] args){
    printOutput( (Object oIn, String sIn) -> {
        System.out.println("Lambda reached!");
        return "lambda return";
    }
    );
}

Ini akan menampilkan:

Lambda reached!
lambda return

Referensi metode serupa. Diberikan:

public class HelperClass{
    public static String testOtherSig(Object o, String s){
        return "real static method";
    }
}

dan utama:

public static void main(String[] args){
    printOutput(HelperClass::testOtherSig);
}

hasilnya akan real static method. Referensi metode dapat berupa statis, instan, non-statis dengan instance acak, dan bahkan konstruktor . Untuk sesuatu yang mirip dengan konstruktor ClassName::newakan digunakan.

1 Ini tidak dianggap lambda oleh beberapa orang, karena memiliki efek samping. Namun, hal itu menggambarkan penggunaan seseorang dengan cara yang lebih mudah divisualisasikan.

nanofarad
sumber
12

Terakhir kali saya memeriksa, Java tidak dapat melakukan apa yang Anda inginkan secara asli; Anda harus menggunakan 'work-arounds' untuk mengatasi keterbatasan tersebut. Sejauh yang saya lihat, antarmuka ADALAH alternatif, tetapi bukan alternatif yang baik. Mungkin siapa pun yang memberi tahu Anda itu artinya seperti ini:

public interface ComponentMethod {
  public abstract void PerfromMethod(Container c);
}

public class ChangeColor implements ComponentMethod {
  @Override
  public void PerfromMethod(Container c) {
    // do color change stuff
  }
}

public class ChangeSize implements ComponentMethod {
  @Override
  public void PerfromMethod(Container c) {
    // do color change stuff
  }
}

public void setAllComponents(Component[] myComponentArray, ComponentMethod myMethod) {
    for (Component leaf : myComponentArray) {
        if (leaf instanceof Container) { //recursive call if Container
            Container node = (Container) leaf;
            setAllComponents(node.getComponents(), myMethod);
        } //end if node
        myMethod.PerfromMethod(leaf);
    } //end looping through components
}

Yang kemudian akan Anda ajukan:

setAllComponents(this.getComponents(), new ChangeColor());
setAllComponents(this.getComponents(), new ChangeSize());
pengguna246091
sumber
6

Jika Anda tidak membutuhkan metode ini untuk mengembalikan sesuatu, Anda bisa membuatnya mengembalikan objek Runnable.

private Runnable methodName (final int arg) {
    return (new Runnable() {
        public void run() {
          // do stuff with arg
        }
    });
}

Kemudian gunakan seperti:

private void otherMethodName (Runnable arg){
    arg.run();
}
Smig
sumber
2

Saya tidak menemukan contoh yang cukup eksplisit bagi saya tentang cara menggunakan java.util.function.Functionmetode sederhana sebagai fungsi parameter. Ini adalah contoh sederhana:

import java.util.function.Function;

public class Foo {

  private Foo(String parameter) {
    System.out.println("I'm a Foo " + parameter);
  }

  public static Foo method(final String parameter) {
    return new Foo(parameter);
  }

  private static Function parametrisedMethod(Function<String, Foo> function) {
    return function;
  }

  public static void main(String[] args) {
    parametrisedMethod(Foo::method).apply("from a method");
  }
}

Pada dasarnya Anda memiliki Fooobjek dengan konstruktor default. A methodyang akan dipanggil sebagai parameter dari parametrisedMethodyang bertipe Function<String, Foo>.

  • Function<String, Foo>berarti bahwa fungsi tersebut mengambil Stringparameter sebagai dan mengembalikan a Foo.
  • The Foo::Methodbersesuaian dengan lambda sepertix -> Foo.method(x);
  • parametrisedMethod(Foo::method) dapat dilihat sebagai x -> parametrisedMethod(Foo.method(x))
  • Pada .apply("from a method")dasarnya harus dilakukanparametrisedMethod(Foo.method("from a method"))

Yang kemudian akan kembali di output:

>> I'm a Foo from a method

Contohnya harus berjalan apa adanya, Anda kemudian dapat mencoba hal-hal yang lebih rumit dari jawaban di atas dengan kelas dan antarmuka yang berbeda.

Sylhare
sumber
untuk menggunakan panggilan yang berlaku di android, Anda memerlukan api minimum 24
Ines Belhouchet
1

Java memang memiliki mekanisme untuk menyampaikan nama dan menyebutnya. Itu adalah bagian dari mekanisme refleksi. Fungsi Anda harus mengambil parameter tambahan dari Metode kelas.

public void YouMethod(..... Method methodToCall, Object objWithAllMethodsToBeCalled)
{
...
Object retobj = methodToCall.invoke(objWithAllMethodsToBeCalled, arglist);
...
}
David Gruzman
sumber
1

Saya bukan ahli java tapi saya memecahkan masalah Anda seperti ini:

@FunctionalInterface
public interface AutoCompleteCallable<T> {
  String call(T model) throws Exception;
}

Saya mendefinisikan parameter di Antarmuka khusus saya

public <T> void initialize(List<T> entries, AutoCompleteCallable getSearchText) {.......
//call here
String value = getSearchText.call(item);
...
}

Akhirnya, saya menerapkan metode getSearchText sambil memanggil metode inisialisasi .

initialize(getMessageContactModelList(), new AutoCompleteCallable() {
          @Override
          public String call(Object model) throws Exception {
            return "custom string" + ((xxxModel)model.getTitle());
          }
        })
Sercan özen
sumber
Sebenarnya itu adalah jawaban terbaik dan cara yang tepat untuk melakukannya. Pantas lagi +1
amdev
0

Gunakan pola Pengamat (kadang-kadang juga disebut pola Pendengar):

interface ComponentDelegate {
    void doSomething(Component component);
}

public void setAllComponents(Component[] myComponentArray, ComponentDelegate delegate) {
    // ...
    delegate.doSomething(leaf);
}

setAllComponents(this.getComponents(), new ComponentDelegate() {
                                            void doSomething(Component component) {
                                                changeColor(component); // or do directly what you want
                                            }
                                       });

new ComponentDelegate()... mendeklarasikan jenis anonim yang mengimplementasikan antarmuka.

EricSchaefer
sumber
8
Ini bukan pola yang Anda cari.
Pete Kirkham
1
Pola pengamat adalah tentang mengabstraksi kemampuan untuk merespons suatu perubahan. OP ingin mengabstraksi tindakan yang diambil pada setiap item dalam koleksi yang jauh dari kode yang berulang pada koleksi, yang merupakan pola pengunjung.
Pete Kirkham
Pola Observer / Listener sebenarnya sama dengan pola Command itu. Mereka hanya berbeda dalam niat. Pengamat adalah tentang pemberitahuan sedangkan perintah adalah pengganti fungsi kelas / lambdas. Pengunjung di sisi lain adalah sesuatu yang sama sekali berbeda. Saya tidak berpikir itu dapat dijelaskan dalam beberapa kalimat jadi silakan lihat di en.wikipedia.org/wiki/Visitor_pattern
EricSchaefer
0

Ini adalah contoh dasarnya:

public class TestMethodPassing
{
    private static void println()
    {
        System.out.println("Do println");
    }

    private static void print()
    {
        System.out.print("Do print");
    }

    private static void performTask(BasicFunctionalInterface functionalInterface)
    {
        functionalInterface.performTask();
    }

    @FunctionalInterface
    interface BasicFunctionalInterface
    {
        void performTask();
    }

    public static void main(String[] arguments)
    {
        performTask(TestMethodPassing::println);
        performTask(TestMethodPassing::print);
    }
}

Keluaran:

Do println
Do print
BullyWiiPlaza
sumber
0

Saya tidak menemukan solusi apa pun di sini yang menunjukkan cara melewatkan metode dengan parameter terikat padanya sebagai parameter metode. Di bawah ini adalah contoh bagaimana Anda dapat melewati metode dengan nilai parameter yang sudah terikat padanya.

  1. Langkah 1: Buat dua antarmuka satu dengan tipe kembali, yang lain tanpa. Java memiliki antarmuka yang sama tetapi mereka kurang praktis digunakan karena mereka tidak mendukung lemparan Exception.


    public interface Do {
    void run() throws Exception;
    }


    public interface Return {
        R run() throws Exception;
    }
  1. Contoh bagaimana kami menggunakan kedua antarmuka untuk membungkus panggilan metode dalam transaksi. Perhatikan bahwa kami melewati metode dengan parameter aktual.


    //example - when passed method does not return any value
    public void tx(final Do func) throws Exception {
        connectionScope.beginTransaction();
        try {
            func.run();
            connectionScope.commit();
        } catch (Exception e) {
            connectionScope.rollback();
            throw e;
        } finally {
            connectionScope.close();
        }
    }

    //Invoke code above by 
    tx(() -> api.delete(6));

Contoh lain menunjukkan cara melewatkan metode yang sebenarnya mengembalikan sesuatu



        public  R tx(final Return func) throws Exception {
    R r=null;
    connectionScope.beginTransaction();
    try {
                r=func.run();
                connectionScope.commit();
            } catch (Exception e) {
                connectionScope.rollback();
                throw e;
            } finally {
                connectionScope.close();
            }
        return r;
        }
        //Invoke code above by 
        Object x= tx(() -> api.get(id));
Stan Sokolov
sumber
0

Contoh solusi dengan refleksi, metode yang lulus harus bersifat publik

import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;

public class Program {
    int i;

    public static void main(String[] args) {
        Program   obj = new Program();    //some object

        try {
            Method method = obj.getClass().getMethod("target");
            repeatMethod( 5, obj, method );
        } 
        catch ( NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            System.out.println( e ); 
        }
    }

    static void repeatMethod (int times, Object object, Method method)
        throws IllegalAccessException, InvocationTargetException {

        for (int i=0; i<times; i++)
            method.invoke(object);
    }
    public void target() {                 //public is necessary
        System.out.println("target(): "+ ++i);
    }
}
zemiak
sumber
0

Saya menghargai jawaban di atas tetapi saya dapat mencapai perilaku yang sama menggunakan metode di bawah ini; sebuah ide yang dipinjam dari panggilan balik Javascript. Saya terbuka untuk koreksi meskipun sejauh ini sangat baik (dalam produksi).

Idenya adalah untuk menggunakan tipe pengembalian fungsi dalam tanda tangan, yang berarti bahwa hasil harus statis.

Di bawah ini adalah fungsi yang menjalankan proses dengan batas waktu.

public static void timeoutFunction(String fnReturnVal) {

    Object p = null; // whatever object you need here

    String threadSleeptime = null;

    Config config;

    try {
        config = ConfigReader.getConfigProperties();
        threadSleeptime = config.getThreadSleepTime();

    } catch (Exception e) {
        log.error(e);
        log.error("");
        log.error("Defaulting thread sleep time to 105000 miliseconds.");
        log.error("");
        threadSleeptime = "100000";
    }

    ExecutorService executor = Executors.newCachedThreadPool();
    Callable<Object> task = new Callable<Object>() {
        public Object call() {
            // Do job here using --- fnReturnVal --- and return appropriate value
            return null;
        }
    };
    Future<Object> future = executor.submit(task);

    try {
        p = future.get(Integer.parseInt(threadSleeptime), TimeUnit.MILLISECONDS);
    } catch (Exception e) {
        log.error(e + ". The function timed out after [" + threadSleeptime
                + "] miliseconds before a response was received.");
    } finally {
        // if task has started then don't stop it
        future.cancel(false);
    }
}

private static String returnString() {
    return "hello";
}

public static void main(String[] args) {
    timeoutFunction(returnString());
}
Joe Mwa
sumber