我正在寻找一种通过引用传递方法的方法。我知道Java不传递方法作为参数,但是,我想要一个替代方案。
我被告知接口是作为参数传递方法的替代方案,但我不理解接口如何通过引用充当方法。如果我理解正确的话,接口只是一组没有定义的抽象方法。我不想发送一个每次都需要定义的接口,因为几个不同的方法可以用相同的参数调用相同的方法。
我想要完成的是类似这样的事情:
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
}
调用方法如下:
setAllComponents(this.getComponents(), changeColor());
setAllComponents(this.getComponents(), changeSize());
上次我检查的时候,Java不能在本地做你想做的事情;你必须使用“变通方法”来绕过这些限制。在我看来,接口是一种选择,但不是一个好的选择。也许告诉你这句话的人的意思是这样的:
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
}
然后你可以调用:
setAllComponents(this.getComponents(), new ChangeColor());
setAllComponents(this.getComponents(), new ChangeSize());
我不是java专家,但我可以这样解决你的问题:
@FunctionalInterface
public interface AutoCompleteCallable<T> {
String call(T model) throws Exception;
}
我在我的特殊接口中定义了参数
public <T> void initialize(List<T> entries, AutoCompleteCallable getSearchText) {.......
//call here
String value = getSearchText.call(item);
...
}
最后,我实现getSearchText方法,同时调用初始化方法。
initialize(getMessageContactModelList(), new AutoCompleteCallable() {
@Override
public String call(Object model) throws Exception {
return "custom string" + ((xxxModel)model.getTitle());
}
})
我很欣赏上面的答案,但我可以使用下面的方法实现相同的行为;这个想法借鉴自Javascript的回调。我对修正持开放态度,尽管到目前为止(在生产中)还不错。
其思想是在签名中使用函数的返回类型,这意味着yield必须是静态的。
下面是一个运行带有超时的进程的函数。
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());
}
自Java 8以来,有一个Function<T, R>接口(docs),它有方法
R apply(T t);
您可以使用它将函数作为参数传递给其他函数。T是函数的输入类型,R是返回类型。
在你的例子中,你需要传递一个函数,它接受Component类型作为输入,并且不返回任何东西——Void。在这种情况下,Function<T, R>不是最好的选择,因为没有Void类型的自动装箱。您正在寻找的接口名为Consumer<T> (docs) with method
void accept(T t);
它看起来是这样的:
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);
}
}
你可以使用方法引用来调用它:
setAllComponents(this.getComponents(), this::changeColor);
setAllComponents(this.getComponents(), this::changeSize);
假设在同一个类中定义了changeColor()和changeSize()方法。
如果你的方法碰巧接受多个参数,你可以使用bifuncfunction <T, U, R> - T和U是输入参数的类型,R是返回类型。还有bicconsumer< T, U>(两个参数,没有返回类型)。不幸的是,对于3个或更多的输入参数,您必须自己创建一个接口。例如:
public interface Function4<A, B, C, D, R> {
R apply(A a, B b, C c, D d);
}
关于如何使用java.util.function.Function作为简单方法的参数函数,我没有找到任何足够明确的示例。这里有一个简单的例子:
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");
}
}
基本上你有一个Foo对象和一个默认构造函数。将作为参数从类型为Function<String, Foo>的parameterisedmethod中调用的方法。
>表示该函数以String作为参数并返回Foo。
Foo::方法对应于类似x的lambda -> Foo. Method (x);
parameterisedmethod (Foo::method)可以被看作x -> parameterisedmethod (Foo.method(x))
apply("from a method")基本上是执行parameterisedmethod (Foo。方法("来自一个方法"))
然后在输出中返回:
>> I'm a Foo from a method
示例应该按原样运行,然后您可以使用不同的类和接口从上面的答案中尝试更复杂的东西。