双冒号(::)运算符是跟函数式接口相关的运算符,作为函数式接口的赋值操作。
双冒号用于静态方法
使用方法:将类的静态方法赋值给一个函数式接口,静态方法的参数个数、类型要跟函数式的接口一致。调用这个函数式接口就相当于调用静态方法。格式ClassName::MethodName
自定义一个函数式接口如下:
java">@FunctionalInterface
public interface FuncInterfaceDemo<T, F>{void accept(T t, F f);
}
测试静态方法赋值给函数式接口
java">public class ColonTestDemo {private String name;public ColonTestDemo(String name) {this.name = name;}public String getName() {return name;}public static void run(ColonTestDemo t, String f) {System.out.println(t.getName() + " said: '" + f+ "'");}public static void main(String[] args) {//测试静态方法ColonTestDemo staticTest = new ColonTestDemo("StaticMethod");FuncInterfaceDemo<ColonTestDemo, String> staticFunc = ColonTestDemo::run;staticFunc.accept(staticTest, "I am a static method");}
}
运行结果如下,相当于调用ColonTestDemo.run(staticTest, “I am a static method”):
双冒号用于构造方法
使用方法:将类的构造方法赋值给一个函数式接口,构造方法的参数个数、类型要跟函数式的接口一致,跟静态方法类似。调用这个函数式接口创建对象。格式ClassName::new
测试构造函数赋值给函数式接口如下:
java">public class ColonTestDemo {private String name;private String desc;public ColonTestDemo(String name, String desc) {this.name = name;this.desc = desc;System.out.println(this.getName() + " said: '" + this.getDesc() + "'");}public String getName() {return name;}public String getDesc() {return desc;}public static void main(String[] args) {//测试构造方法FuncInterfaceDemo<String, String> newFunc = ColonTestDemo::new;newFunc.accept("Constructor", "I am a constructor method");}}
运行结果如下,相当于调用 new ColonTestDemo(“Constructor”, “I am a constructor method”):
双冒号用于成员方法
使用方法:将类的成员方法赋值给一个函数式接口,成员方法的参数个数要比函数式的接口少1个,因为对象本身作为第一个参数传给函数式接口。调用这个函数式接口相当于执行对象的成员方法。格式ClassName::MethodName
java">public class ColonTestDemo {private String name;public ColonTestDemo(String name) {this.name = name;}public void run(String f) {System.out.println(name + " said: '" + f + "'");}public static void main(String[] args) {//测试成员方法ColonTestDemo instTest = new ColonTestDemo("InstMethod");FuncInterfaceDemo<ColonTestDemo, String> instFun = ColonTestDemo::run;instFun.accept(instTest, "I am a inst method");}
}
运行结果如下,相当于调用instTest.run(“I am a inst method”):
如果成员方法参数个数跟接口一致(不是少1个),编译报错"Non-static method cannot be referenced from a static context"。因为编译器认为需要一个静态方法来匹配,但实际不是一个静态方法。
或者赋值时使用对象的冒号方法:colonTestDemo::run,参数就可以和接口数一致。
java">public class ColonTestDemo {private String name;public ColonTestDemo(String name) {this.name = name;}public void run(String t, String f) {System.out.println(name + " said: '" + f + "'");}public static void main(String[] args) {//测试成员方法ColonTestDemo instTest = new ColonTestDemo("InstMethod");FuncInterfaceDemo<String, String> instFun = ColonTestDemo::run;// 或者用实例的run方法即可,则不会出现下图的错误。FuncInterfaceDemo<String, String> instFun = instTest::run;}
}
如果函数式接口第一个参数类型不是对象的类型,也编译报错"类型不兼容"。因为第一个实参是对象的类型,而函数式接口的第一个形参不是对象的类型。
java">public class ColonTestDemo {private String name;public ColonTestDemo(String name) {this.name = name;}public void run(String f) {System.out.println(name + " said: '" + f + "'");}public static void main(String[] args) {//测试成员方法ColonTestDemo instTest = new ColonTestDemo("InstMethod");FuncInterfaceDemo<String, ColonTestDemo> instFun = ColonTestDemo::run;}
}