我需要一个“接受参数的Runnable”,尽管我知道这样的runnable并不真正存在。
这可能表明我的应用程序设计中存在根本缺陷和/或我疲惫的大脑中的精神障碍,因此我希望在这里找到一些关于如何完成类似以下事情的建议,而不违反基本的面向对象原则:
private Runnable mOneShotTask = new Runnable(String str) {
public void run(String str) {
someFunc(str);
}
};
知道如何完成上述事情吗?
自从我最初发布这篇文章以来已经快 9 年了,说实话,从那时起 Java 已经做了一些改进。我将在下面留下我原来的答案,但人们没有必要做其中的事情。 9 年前,在代码审查期间,我会质疑他们为什么这样做,也许会批准,也许不会。有了现代 lambda 表达式,如此高票数的答案推荐过时的方法(平心而论,一开始就可疑……)是不负责任的。在现代 Java 中,代码审查将立即被拒绝,这将是建议:
void foo(final String str) {
Thread t = new Thread(() -> someFunc(str));
t.start();
}
和以前一样,像以有意义的方式处理该线程这样的细节留给读者作为练习。但说白了,如果你害怕使用 lambda,那么你应该更害怕多线程系统。
原答案,只是因为:
您可以在方法中直接声明一个类
void Foo(String str) {
class OneShotTask implements Runnable {
String str;
OneShotTask(String s) { str = s; }
public void run() {
someFunc(str);
}
}
Thread t = new Thread(new OneShotTask(str));
t.start();
}
你可以把它放在一个函数中。
String paramStr = "a parameter";
Runnable myRunnable = createRunnable(paramStr);
private Runnable createRunnable(final String paramStr){
Runnable aRunnable = new Runnable(){
public void run(){
someFunc(paramStr);
}
};
return aRunnable;
}
(当我使用这个时,我的参数是一个整数 ID,我用它来制作 ID --> myRunnables 的哈希图。这样,我可以使用哈希图在处理程序中发布/删除不同的 myRunnable 对象。)
theView.post(new Runnable() {
String str;
@Override
public void run() {
par.Log(str);
}
public Runnable init(String pstr) {
this.str=pstr;
return(this);
}
}.init(str));
创建返回对象本身的 init 函数并用它初始化参数。
从 Java 8 开始,最好的答案是使用
Consumer<T>
:
https://docs.oracle.com/javase/8/docs/api/java/util/function/Consumer.html
它是函数式接口之一,这意味着你可以将它作为 lambda 表达式来调用:
void doSomething(Consumer<String> something) {
something.accept("hello!");
}
...
doSomething( (something) -> System.out.println(something) )
...
我使用以下实现 Runnable 接口的类。使用此类,您可以轻松创建带参数的新线程
public abstract class RunnableArg implements Runnable {
Object[] m_args;
public RunnableArg() {
}
public void run(Object... args) {
setArgs(args);
run();
}
public void setArgs(Object... args) {
m_args = args;
}
public int getArgCount() {
return m_args == null ? 0 : m_args.length;
}
public Object[] getArgs() {
return m_args;
}
}
您有两个选择:
定义一个命名类。将您的参数传递给指定类的构造函数。
让你的匿名类关闭你的“参数”。请务必将其标记为
final
。我首先想知道您在这里想要完成什么,需要将参数传递给 new Runnable() 或 run()。 通常的方法应该是拥有一个 Runnable 对象,在启动之前通过设置成员变量将 data(str) 传递给其线程。 run() 方法然后使用这些成员变量值来执行 someFunc()
/**
* @author AbdelWadoud Rasmi
* <p>
* The goal of this class is to pass some parameters to a runnable instance, a good example is
* after caching a file you need to pass the new path to user to do some work on it.
*/
public abstract class ParameterizedRunnable implements Runnable {
private Object[] params;
/**
* @param params: parameters you want to pass the the runnable.
*/
public ParameterizedRunnable(Object... params) {
this.params = params;
}
/**
* Code you want to run
*
* @param params:parameters you want to pass the the runnable.
*/
protected abstract void run(Object... params);
@Override
public final void run() {
run(params);
}
/**
* setting params
*/
public void setParams(Object... params) {
this.params = params;
}
/**
* getting params
*/
public Object[] getParams() {
return params;
}
}
迄今为止最好的方法:
Consumer<String> oneShot = str -> {
somefunc(str);
};
oneShot.accept("myString");
创建一个实现 Runnable 的新类。在此类中,您可以通过选择抽象方法来扩展 run() 方法。
public abstract class CCallback implements Runnable {
@Override
public void run() {}
public abstract void run(Object any);
}
现在您可以使用此类作为回调函数,如下所示:
public void whatever(CCallback callback) {
String any = "any type of param";
if (callback != null)
callback.run(any);
}
“Whatever”方法现在可以在我们的可运行对象运行之前完成其任务:
whatever(new CCallback() {
@Override
public void run(Object any) {
// Here you can reach "any"
}
});
如果条件允许,你可以简单地这样做。
方法.java
public interface Method {
void run(String msg);
}
用途:
private Method mOneShotTask = (str) -> someFunc(str);