Java: параметризованный Runnable - PullRequest
16 голосов
/ 02 ноября 2009

Стандартный Runnable интерфейс имеет только непараметризованный метод run().Существует также интерфейс Callable<V> с методом call(), возвращающим результат универсального типа.Мне нужно передать универсальный параметр, что-то вроде этого:

<code>interface MyRunnable<E> {
  public abstract void run(E reference);
}
Существует ли какой-либо стандартный интерфейс для этой цели или я должен объявить этот базовый самостоятельно?

Ответы [ 6 ]

13 голосов
/ 02 ноября 2009

Обычно вы реализуете Runnable или Callable как класс, который поддерживает универсальный входной параметр; например,

public class MyRunnable<T> implements Runnable {
  private final T t;

  public MyRunnable(T t) {
    this.t = t;
  }

  public void run() {
    // Reference t.
  }
}
9 голосов
/ 02 ноября 2009

Существует также <a href="http://docs.guava-libraries.googlecode.com/git-history/HEAD/javadoc/com/google/common/base/Function.html" rel="nofollow noreferrer">com.google.common.base.Function<F, T></a> из Коллекции Google Гуава .

Если вы установите тип вывода на ? или Void (и всегда будете возвращать null), вы можете использовать его как альтернативу Runnable с входным параметром.

Преимущество заключается в возможности использования Functions.compose для преобразования входного значения, Iterables.transform для применения его к каждому элементу коллекции и т. Д.

8 голосов
/ 31 января 2016

Java 8 включает в себя интерфейс java.util.function.Consumer<T> с единственным методом, отличным от значения по умолчанию void accept(T t).

Есть много других связанных интерфейсов в этом пакете .

3 голосов
/ 02 ноября 2009

Как правило, если вы хотите передать параметр в метод run(), вы создадите подкласс Runnable с помощью конструктора, который принимает параметр.

Например, вы хотите сделать это:

// code
Runnable r = new YourRunnable();
r.run(someParam);
//more code

Вам нужно сделать это:

// code
Runnable r = new YourRunnable(someParam);
r.run();
//more code

Вы будете реализовывать YourRunnable аналогично приведенному ниже:

public class YourRunnable implements Runnable {
    Some param;
    public YourRunnable(Some param){
        this.param = param;
    }
    public void run(){
        // do something with param
    }
}
0 голосов
/ 02 ноября 2009

Я предлагаю определить интерфейс, как в первоначальном вопросе. Кроме того, избегайте слабой типизации, сделав интерфейс специфичным для того, что он должен делать, а не бессмысленный интерфейс, такой как Runnable.

0 голосов
/ 02 ноября 2009

Runnable не предназначен для непосредственного вызова клиентским кодом, таким как foo.run(), который будет последовательно выполняться в текущем потоке.

Из Runnable API :

Интерфейс Runnable должен быть реализуется любым классом, чей экземпляры предназначены для выполнения по теме Класс должен определить метод без аргументов называется run.

Этот интерфейс предназначен для обеспечения общий протокол для объектов, которые хотите выполнить код, пока они активный. Например, Runnable это реализуется классом Thread. бытие активный просто означает, что поток имеет было начато и еще не было остановился.

Кроме того, Runnable обеспечивает означает, что класс будет активным в то время как не подкласс Класс, который реализует Runnable может работать без создание подклассов Thread путем создания экземпляра Экземпляр потока и передача себя в как цель. В большинстве случаев Запускаемый интерфейс следует использовать, если вы только планируете переопределить метод run () и никакой другой поток методы. Это важно потому что классы не должны быть разделены на подклассы если программист не намерен изменение или усиление фундаментального поведение класса.

Вместо этого вы создаете новый экземпляр Thread на основе вашего работоспособного объекта, а затем вызываете bar.start(). В этом случае JVM отвечает за вызов run() в этом отдельном потоке.

Пример:

 public class Foo<E> implements Runnable {
     private final E e;
     public Foo(E e) { ... }
     @Override
     public void run() {
         do something with e.
     }
 }

 Foo<String> foo = new Foo("hello");
 Thread bar = new Thread(foo);
 bar.start();
...