Java 使用双冒号(:)在ExecuterService中调用方法
我有一个类分别由静态和非静态两个方法组成,根据我的有限知识,提交方法直接或通过lamba表达式接受可运行、可调用的实例 今天我了解到,我们甚至可以使用Java8中添加的双冒号直接调用或触发静态和非静态方法 我只是想知道这是如何工作的,我的类中没有run方法,它也没有实现runnable,甚至我没有使用lamba 使用::是一种好的做法,还是应该传递可运行或可调用的实例 有没有其他方法可以在submit()中调用方法而不是传递实例Java 使用双冒号(:)在ExecuterService中调用方法,java,multithreading,java-8,concurrency,executorservice,Java,Multithreading,Java 8,Concurrency,Executorservice,我有一个类分别由静态和非静态两个方法组成,根据我的有限知识,提交方法直接或通过lamba表达式接受可运行、可调用的实例 今天我了解到,我们甚至可以使用Java8中添加的双冒号直接调用或触发静态和非静态方法 我只是想知道这是如何工作的,我的类中没有run方法,它也没有实现runnable,甚至我没有使用lamba 使用::是一种好的做法,还是应该传递可运行或可调用的实例 有没有其他方法可以在submit()中调用方法而不是传递实例 Class A { public static void pri
Class A {
public static void printSomething(){
System.out.println("Staitc Method");
}
public void print()
{
System.out.println("Non-Staitc Method");
}
}
psvm()
{
A a = new A():
ExecutorService es = Executors.newFixedThreadPool(2);
es.submit(A::printSomething); //Expected is runnable or callable task
es.submit(a::print);
}
A::printSomething
称为方法引用。当您在需要Runnable或Callable等接口的地方使用方法引用时,Java会自动创建调用该方法的接口的实现
就是
es.submit(A::printSomething);
行为与
es.submit(new Runnable() {
public void run() {
A.printSomething();
}
});
但是更易于阅读,并且不会在使用它的任何地方创建新类,也不会在每次调用它时创建新的对象实例
您可以在中阅读有关方法引用的更多信息
由于
Runnable
是一个函数,因此即使方法名称不匹配,也可以使用适合它的lambda表达式或方法引用。因此,任何无参数void方法都可以用作可运行的
Runnable r1 = () -> a.printSomething();
Runnable r2 = A::printSomething(); // Method reference, short-hand
Runnable r3 = () -> A.printSomething(); // Same as r2, but as explicit lambda expression
即使类没有实现void run()
方法,方法引用仍然有效的原因是函数接口分配的关键是方法签名,而不是方法名称
A
的printSomething
的方法签名与Runnable
的run
匹配,因此它可以工作。请注意,这只适用于功能接口(即只有一个方法的接口,所述方法没有默认实现)
这是个好习惯吗?这是一个风格问题,但使用方法引用肯定不是一个坏习惯,而且它们比left->right
lambdas更简洁
我建议你自己试试,这样你就清楚了规则
public class FunctionalInterfaceDemo {
public static class SimpleClass {
public static void doItStatic() {
}
public void doItNonStatic() {
}
}
interface MyOwnFunctionalInterface {
void methodA();
}
interface NotAFunctionalInterface {
void methodA();
void methodB();
}
interface AlsoNotAFunctionalInterface {
default void methodA() {
}
}
public static void main(String[] args) {
MyOwnFunctionalInterface compiles = SimpleClass::doItStatic;
MyOwnFunctionalInterface alsoCompiles = new SimpleClass()::doItNonStatic;
NotAFunctionalInterface doesNotCompile = SimpleClass::doItStatic;
AlsoNotAFunctionalInterface alsoDoesNotCompile = SimpleClass::doItStatic;
}
}您可以es.submit(()->{//code/invoke a void method here})代码>。run
方法调用您的print
方法。@Naman这是lambda表达式,它可以工作,间接地说,它是run方法,但是::如何工作?链接的问题很好地回答了不同答案中的不同示例。是的,关键术语是“函数接口”1+对于不同的方法,每次使用方法引用是一种好的做法吗?@Shelly我想这取决于你问谁。对于无参数的方法来说,这没有多大区别,但是当方法有参数时,使用显式版本(a,b)->foo(a,b)
与this::foo
,例如在使用流时,它会变得更清晰。@Kayaman感谢manYou示例真的很有帮助
public class FunctionalInterfaceDemo {
public static class SimpleClass {
public static void doItStatic() {
}
public void doItNonStatic() {
}
}
interface MyOwnFunctionalInterface {
void methodA();
}
interface NotAFunctionalInterface {
void methodA();
void methodB();
}
interface AlsoNotAFunctionalInterface {
default void methodA() {
}
}
public static void main(String[] args) {
MyOwnFunctionalInterface compiles = SimpleClass::doItStatic;
MyOwnFunctionalInterface alsoCompiles = new SimpleClass()::doItNonStatic;
NotAFunctionalInterface doesNotCompile = SimpleClass::doItStatic;
AlsoNotAFunctionalInterface alsoDoesNotCompile = SimpleClass::doItStatic;
}