为什么不允许AppTest::makeUppercase
?
简短的回答是AppTest::makeUppercase
无效“对特定类型的任意对象的实例方法的引用”.
AppTest::makeUppercase
必须实现接口Function<AppTest, String>
为有效参考。
Details:
有4 https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html#staticJava中方法引用的种类:
-
ContainingClass::staticMethodName
- 静态方法的引用
-
containingObject::instanceMethodName
- 对特定对象的实例方法的引用
-
ContainingType::methodName
- 对特定类型的任意对象的实例方法的引用
-
ClassName::new
- 对构造函数的引用
每一种方法引用都需要对应的Function
接口实现。
您可以使用对特定类型的任意对象的实例方法的引用作为参数。
这种方法引用在方法引用中没有显式的参数变量,需要实现接口Function<ContainingType, String>
。换句话说,左操作数的类型必须是AppTest
使AppTest::makeUppercase
可编译。String::toUpperCase
工作正常,因为参数类型和实例类型相同 -String
.
import static java.lang.System.out;
import java.util.Arrays;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.function.UnaryOperator;
class ReferenceSource {
private String value;
public ReferenceSource() {
}
public ReferenceSource(String value) {
this.value = value;
}
public String doInstanceMethodOfParticularObject(final String value) {
return ReferenceSource.toUpperCase(value);
}
public static String doStaticMethod(final String value) {
return ReferenceSource.toUpperCase(value);
}
public String doInstanceMethodOfArbitraryObjectOfParticularType() {
return ReferenceSource.toUpperCase(this.value);
}
private static String toUpperCase(final String value) {
return Optional.ofNullable(value).map(String::toUpperCase).orElse("");
}
}
public class Main {
public static void main(String... args) {
// #1 Ref. to a constructor
final Supplier<ReferenceSource> refConstructor = ReferenceSource::new;
final Function<String, ReferenceSource> refParameterizedConstructor = value -> new ReferenceSource(value);
final ReferenceSource methodReferenceInstance = refConstructor.get();
// #2 Ref. to an instance method of a particular object
final UnaryOperator<String> refInstanceMethodOfParticularObject = methodReferenceInstance::doInstanceMethodOfParticularObject;
// #3 Ref. to a static method
final UnaryOperator<String> refStaticMethod = ReferenceSource::doStaticMethod;
// #4 Ref. to an instance method of an arbitrary object of a particular type
final Function<ReferenceSource, String> refInstanceMethodOfArbitraryObjectOfParticularType = ReferenceSource::doInstanceMethodOfArbitraryObjectOfParticularType;
Arrays.stream(new String[] { "a", "b", "c" }).map(refInstanceMethodOfParticularObject).forEach(out::print);
Arrays.stream(new String[] { "d", "e", "f" }).map(refStaticMethod).forEach(out::print);
Arrays.stream(new String[] { "g", "h", "i" }).map(refParameterizedConstructor).map(refInstanceMethodOfArbitraryObjectOfParticularType)
.forEach(out::print);
}
}
此外,您可以看看this https://stackoverflow.com/questions/49349261/method-reference-difference-to-lambda and that https://stackoverflow.com/questions/23533345/what-does-an-arbitrary-object-of-a-particular-type-mean-in-java-8 thread.