静态和实例方法的方法参考
Method reference for static and instance methods
在 Java
中的实例方法的情况下,我无法掌握方法引用的概念
例如在下面的示例中,编译器在列表行中给出错误。
我看过String::toUpperCase的例子。
我对以下这一点感到困惑
(1) String是一个class,toUpperCase是实例方法。 Java 允许 String::toUpperCase
(2) 为什么在我的情况下不允许:- AppTest::makeUppercase
package mja;
import java.util.function.Function;
public class AppTest {
public String makeUppercase(String source){
return source.toUpperCase();
}
public void printFormattedString(String string, Function<String, String> formatter){
System.out.println(formatter.apply(string));
}
public static void main(String[] args) {
AppTest appTest = new AppTest();
String source = "Hello World!";
// Below statement compiled successfully
appTest.printFormattedString(source, appTest::makeUppercase);
// Getting error that non-static method can't be referenced from static context
appTest.printFormattedString(source, AppTest::makeUppercase);
}
}
String::toUpperCase
是
的简写
text -> {
return text.toUpperCase();
}
又是
的短版
new Functon<String, String> (String text) {
Override
public String apply(String text) {
return text.toUpperCase();
}
}
所以当你想要 AppTest::myMethod
你需要
public class AppTest {
public String myMethod(){
return this.toString();
}
public void printFormattedString2(AppTest appTest, Function<AppTest, String> formatter){
System.out.println(formatter.apply(appTest));
}
public static void main(String[] args) {
AppTest appTest = new AppTest();
appTest.printFormattedString2(appTest, AppTest::myMethod);
}
}
因为整个版本看起来都是这样
appTest.printFormattedString2(appTest, new Function<AppTest, String>() {
@Override
public String apply(AppTest text) {
return text.makeUppercase2();
}
});
为简单起见,让我们按如下方式编辑您的 class。
public class AppTest {
private String name;
public AppTest(String name){ this.name = name; }
public String makeUppercase() { //I have removed the argument here!!
return this.name.toUpperCase();
}
psvm main(){
AppTest appTest = new AppTest("Hello");
Stream.of(appTest).map(AppTest::makeUppercase).forEach(System.out::println);
//Here makeUppercase works of objects of type AppData similar to how String::toUpperCase works on object of type String!
}
}
已接受。为什么?
这里,AppTest::makeUppercase
是在AppTest
的this
实例上运行的实例方法。
为什么你的不工作?
appTest.printFormattedString(source, AppTest::makeUppercase);
这是行不通的,因为您需要通过 Function
的实施。而且,makeUpperCase() Function
无法从非静态上下文访问,因为方法 makeUpperCase()
适用于类型 AppData
的对象。所以,你需要AppData
个实例来调用这个方法!
也许你应该把你的方法改成静态的,然后像这样使用它,
appTest.printFormattedString("Hello", AppTest::makeUppercase);
为什么以下代码有效?
appTest.printFormattedString(source, appTest::makeUppercase);
因为,您创建了 AppTest
的实例并访问 makeUppercase
方法(即实现)并将其作为参数传递给 printFormattedString
。
您需要特定类型的对象才能访问非静态方法。但是,您不需要特定类型的对象来访问静态方法。
String::toUpperCase
适用于 String
的实例。但是如果没有要处理的 String
对象,您将无法访问此方法。请参阅我在代码块中的评论以更好地理解这一点。
为什么不允许 AppTest::makeUppercase
?
简短的回答是 AppTest::makeUppercase
无效 “对特定类型的任意对象的实例方法的引用”。
AppTest::makeUppercase
必须实现接口 Function<AppTest, String>
才能成为有效引用。
详情:
Java中有4种方法引用:
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);
}
}
此外,您可以查看 and that 话题。
在 Java
中的实例方法的情况下,我无法掌握方法引用的概念例如在下面的示例中,编译器在列表行中给出错误。
我看过String::toUpperCase的例子。
我对以下这一点感到困惑 (1) String是一个class,toUpperCase是实例方法。 Java 允许 String::toUpperCase (2) 为什么在我的情况下不允许:- AppTest::makeUppercase
package mja;
import java.util.function.Function;
public class AppTest {
public String makeUppercase(String source){
return source.toUpperCase();
}
public void printFormattedString(String string, Function<String, String> formatter){
System.out.println(formatter.apply(string));
}
public static void main(String[] args) {
AppTest appTest = new AppTest();
String source = "Hello World!";
// Below statement compiled successfully
appTest.printFormattedString(source, appTest::makeUppercase);
// Getting error that non-static method can't be referenced from static context
appTest.printFormattedString(source, AppTest::makeUppercase);
}
}
String::toUpperCase
是
的简写text -> {
return text.toUpperCase();
}
又是
的短版new Functon<String, String> (String text) {
Override
public String apply(String text) {
return text.toUpperCase();
}
}
所以当你想要 AppTest::myMethod
你需要
public class AppTest {
public String myMethod(){
return this.toString();
}
public void printFormattedString2(AppTest appTest, Function<AppTest, String> formatter){
System.out.println(formatter.apply(appTest));
}
public static void main(String[] args) {
AppTest appTest = new AppTest();
appTest.printFormattedString2(appTest, AppTest::myMethod);
}
}
因为整个版本看起来都是这样
appTest.printFormattedString2(appTest, new Function<AppTest, String>() {
@Override
public String apply(AppTest text) {
return text.makeUppercase2();
}
});
为简单起见,让我们按如下方式编辑您的 class。
public class AppTest {
private String name;
public AppTest(String name){ this.name = name; }
public String makeUppercase() { //I have removed the argument here!!
return this.name.toUpperCase();
}
psvm main(){
AppTest appTest = new AppTest("Hello");
Stream.of(appTest).map(AppTest::makeUppercase).forEach(System.out::println);
//Here makeUppercase works of objects of type AppData similar to how String::toUpperCase works on object of type String!
}
}
已接受。为什么?
这里,AppTest::makeUppercase
是在AppTest
的this
实例上运行的实例方法。
为什么你的不工作?
appTest.printFormattedString(source, AppTest::makeUppercase);
这是行不通的,因为您需要通过 Function
的实施。而且,makeUpperCase() Function
无法从非静态上下文访问,因为方法 makeUpperCase()
适用于类型 AppData
的对象。所以,你需要AppData
个实例来调用这个方法!
也许你应该把你的方法改成静态的,然后像这样使用它,
appTest.printFormattedString("Hello", AppTest::makeUppercase);
为什么以下代码有效?
appTest.printFormattedString(source, appTest::makeUppercase);
因为,您创建了 AppTest
的实例并访问 makeUppercase
方法(即实现)并将其作为参数传递给 printFormattedString
。
您需要特定类型的对象才能访问非静态方法。但是,您不需要特定类型的对象来访问静态方法。
String::toUpperCase
适用于 String
的实例。但是如果没有要处理的 String
对象,您将无法访问此方法。请参阅我在代码块中的评论以更好地理解这一点。
为什么不允许 AppTest::makeUppercase
?
简短的回答是 AppTest::makeUppercase
无效 “对特定类型的任意对象的实例方法的引用”。
AppTest::makeUppercase
必须实现接口 Function<AppTest, String>
才能成为有效引用。
详情:
Java中有4种方法引用:
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);
}
}
此外,您可以查看