Есть ли способ получить аргумент в вызываемом методе? - PullRequest
36 голосов
/ 03 апреля 2012

Я создал фрагмент кода, который берет IP-адрес (из основного метода в другом классе), а затем перебирает диапазон IP-адресов, проверяя каждый из них на ходу. У меня есть интерфейс GUI на этом, и он зависал (поэтому я и сделал многопоточность. Моя проблема в том, что я больше не могу принимать IP-адрес в качестве аргумента в своем коде ping как вызываемый. Я искал все для этого и, кажется, не могу найти способ обойти это. Есть ли способ для вызываемого метода принимать аргументы? Если нет, есть ли другой способ выполнить то, что я пытаюсь сделать?

образец моего кода:

public class doPing implements Callable<String>{

public String call() throws Exception{

    String pingOutput = null;

    //gets IP address and places into new IP object
    InetAddress IPAddress = InetAddress.getByName(IPtoPing);
    //finds if IP is reachable or not. a timeout timer of 3000 milliseconds is set.
    //Results can vary depending on permissions so cmd method of doing this has also been added as backup
    boolean reachable = IPAddress.isReachable(1400);

    if (reachable){
          pingOutput = IPtoPing + " is reachable.\n";
    }else{
        //runs ping command once on the IP address in CMD
        Process ping = Runtime.getRuntime().exec("ping " + IPtoPing + " -n 1 -w 300");
        //reads input from command line
        BufferedReader in = new BufferedReader(new InputStreamReader(ping.getInputStream()));
        String line;
        int lineCount = 0;
        while ((line = in.readLine()) != null) {
            //increase line count to find part of command prompt output that we want
            lineCount++;
            //when line count is 3 print result
            if (lineCount == 3){
                pingOutput = "Ping to " + IPtoPing + ": " + line + "\n";
            }
        }
    }
    return pingOutput;
}
}

IPtoPing использовался в качестве аргумента, который был взят.

Ответы [ 6 ]

47 голосов
/ 03 апреля 2012

Вы не можете передать его в качестве аргумента call(), поскольку сигнатура метода не позволяет этого.

Однако вы можете передать его в качестве аргумента конструктора;например,

public class DoPing implements Callable<String>{
    private final String ipToPing;

    public DoPing(String ipToPing) {
        this.ipToPing = ipToPing;
    }

    public String call() throws SomeException {
        InetAddress ipAddress = InetAddress.getByName(ipToPing);
        ....
    }
}

(я исправил несколько вопиющих нарушений стиля кода !!)

Кроме того, вы можете:

  • объявить DoPingкак внутренний класс, и пусть он ссылается на final ipToPing во входящей области или

  • добавить метод setIpToPing(String ipToPing).

(Последнее позволяет повторно использовать объект DoPing, но недостатком является то, что вам потребуется синхронизация для безопасного доступа к нему.)

7 голосов
/ 03 апреля 2012

Добавление к ответу Jarle - в случае, если вы создаете Callable как экземпляр анонимного класса, вы можете использовать поле final вне анонимного класса для передачи данных в экземпляр:

    final int arg = 64;
    executor.submit(new Callable<Integer>() {
        public Integer call() throws Exception {
            return arg * 2;
        }
    });
5 голосов
/ 14 июня 2016

Вы не можете передавать аргументы call(), потому что сигнатура метода не позволяет этого, но вот как минимум один способ обойти это,

  1. определение абстрактного класса, который охватывает / реализует Callable и
  2. внедряет установщик для "внедрения" результата в call()

Определите абстрактный класс:

import java.util.concurrent.Callable;

public abstract class Callback<T> implements Callable<Void> {
    T result;

    void setResult (T result) {
        this.result = result;
    }

    public abstract Void call ();
}

Определите метод, который должен вызывать обратный вызов:

public void iWillFireTheCallback (Callback callback) {
    // You could also specify the signature like so:
    // Callback<Type of result> callback

    // make some information ("the result")
    // available to the callback function:
    callback.setResult("Some result");

    // fire the callback:
    callback.call();
}

В том месте, куда вы хотите позвонить iWillFireTheCallback:

Определить функцию обратного вызова (даже возможно внутри методов):

class MyCallback extends Callback {
    @Override
    public Void call () {
        // this is the actual callback function

        // the result variable is available right away:
        Log.d("Callback", "The result is: " + result);

        return null;
    }
}

А затем позвонить iWillFireTheCallback при передаче обратного вызова:

iWillFireTheCallback(new MyCallback());
5 голосов
/ 03 апреля 2012

Когда вы создаете doPing-класс (должен быть заглавной буквой в имени класса), отправьте ip-адрес в конструктор. Используйте этот ip-адрес в методе вызова.

3 голосов
/ 03 апреля 2012

Поместите несколько (final) полей в ваш класс doPing и конструктор, который их инициализирует, затем передайте значения, которые вы хотите использовать в call(), конструктору doPing:

public class doPing implements Callable<String>  {
     private final String ipToPing;

     public doPing(String ip) {
         this.ipToPing = ip;
     }

     public String call() {
         // use ipToPing
     }
}
1 голос
/ 03 апреля 2012

Вы должны определить свойство, такое как ipAddress и его метод доступа. и передав его значение в constructor или setter методом. В doPing классе используйте ipAddress свойство.

class DoPing/* In java all classes start with capital letter */implements Callable<String>
{
    private String  ipAddress;

    public String getIpAddress()
    {
        return ipAddress;
    }

    public void setIpAddress(String ipAddress)
    {
        this.ipAddress = ipAddress;
    }

    /*
     * Counstructor 
     */
    public DoPing(String ipAddress )
    {
        this.ipAddress = ipAddress;
    }

    @Override
    public String call() throws Exception
    {
        // your logic
    }
}
...