::
称为方法引用。它基本上是对单个方法的引用。即,它通过名称引用现有方法。
简短说明:
下面是对静态方法的引用示例:
class Hey {
public static double square(double num){
return Math.pow(num, 2);
}
}
Function<Double, Double> square = Hey::square;
double ans = square.apply(23d);
square
可以像对象引用一样传递,并在需要时触发。事实上,它可以像引用对象的“正常”方法一样容易地使用。例如:static
class Hey {
public double square(double num) {
return Math.pow(num, 2);
}
}
Hey hey = new Hey();
Function<Double, Double> square = hey::square;
double ans = square.apply(23d);
Function
以上是一个功能接口。要完全理解,理解函数接口也很重要。显然,功能接口是只有一个抽象方法的接口。::
功能接口的示例包括 、 和 。Runnable
Callable
ActionListener
Function
上面是一个功能接口,只有一种方法:。它采用一个参数并生成结果。apply
s很棒的原因是:::
方法引用是与 lambda 表达式 (...) 具有相同处理方式的表达式,但它们不是提供方法主体,而是按名称引用现有方法。
例如,而不是编写 lambda 主体
Function<Double, Double> square = (Double x) -> x * x;
你可以简单地做
Function<Double, Double> square = Hey::square;
在运行时,这两种方法的行为彼此完全相同。字节码可能相同,也可能不同(尽管对于上述情况,将生成相同的字节码;编译上述字节码并检查 )。square
javap -c
要满足的唯一主要标准是:您提供的方法应具有与您用作对象引用的功能接口的方法相似的签名。
以下行为是非法的:
Supplier<Boolean> p = Hey::square; // illegal
square
需要一个参数并返回一个 .Supplier 中的方法返回一个值,但它不采用参数。因此,这会导致错误。double
get
方法引用是指功能接口的方法。(如前所述,功能接口每个只能有一个方法。
其他一些示例:Consumer 中的方法接受输入,但它不返回任何内容。accept
Consumer<Integer> b1 = System::exit; // void exit(int status)
Consumer<String[]> b2 = Arrays::sort; // void sort(Object[] a)
Consumer<String> b3 = MyProgram::main; // void main(String... args)
class Hey {
public double getRandom() {
return Math.random();
}
}
Callable<Double> call = hey::getRandom;
Supplier<Double> call2 = hey::getRandom;
DoubleSupplier sup = hey::getRandom;
// Supplier is functional interface that takes no argument and gives a result
在上面,不采用任何参数并返回 .因此,可以使用任何满足以下条件的函数接口:不取参数并返回。getRandom
double
double
另一个例子:
Set<String> set = new HashSet<>();
set.addAll(Arrays.asList("leo","bale","hanks"));
Predicate<String> pred = set::contains;
boolean exists = pred.test("leo");
如果是参数化类型:
class Param<T> {
T elem;
public T get() {
return elem;
}
public void set(T elem) {
this.elem = elem;
}
public static <E> E returnSame(E elem) {
return elem;
}
}
Supplier<Param<Integer>> obj = Param<Integer>::new;
Param<Integer> param = obj.get();
Consumer<Integer> c = param::set;
Supplier<Integer> s = param::get;
Function<String, String> func = Param::<String>returnSame;
方法引用可以有不同的样式,但从根本上说,它们都意味着同样的事情,并且可以简单地可视化为lambdas:
- 静态方法 (
ClassName::methName
)
- 特定对象的实例方法 (
instanceRef::methName
)
- 特定对象的超方法 (
super::methName
)
- 特定类型的任意对象的实例方法 (
ClassName::methName
)
- 类构造函数引用 (
ClassName::new
)
- 数组构造函数引用 (
TypeName[]::new
)
有关进一步的参考,请参阅 Lambda 的状态。