请解释 Java 8 方法引用实例方法使用 class 名称
Please Explain Java 8 Method Reference to instance Method using class name
public interface MyFunc<T> {
boolean func(T v1, T v2);
}
public class HighTemp {
private int hTemp;
HighTemp(){
}
public HighTemp(int ht) {
this.hTemp = ht;
}
boolean sameTemp(HighTemp ht2){
return hTemp == ht2.hTemp;
}
boolean lessThanTemp(HighTemp ht2){
return hTemp < ht2.hTemp;
}
}
class InstMethWithObjRef {
static <T> int counter(T[] vals, MyFunc<T> f, T v){
int count = 0;
for (int i = 0; i < vals.length; i++) {
if(f.func(vals[i], v)) count++;
}
return count;
}
public static void main(String[] args) {
int count;
//Create an array of HighTemp objects.
HighTemp[] weekDayHighs = {new HighTemp(89), new HighTemp(82),
new HighTemp(90), new HighTemp(89),
new HighTemp(89), new HighTemp(91),
new HighTemp(84), new HighTemp(83)};
count = counter(weekDayHighs, HighTemp::lessThanTemp,new HighTemp(89));
System.out.println(count);
}
}
请解释如何
boolean sameTemp()
与函数接口中的 func()
兼容。
sameTemp()
方法在 func()
上在功能接口中实现。
count = counter(weekDayHighs, HighTemp::sameTemp, new HighTemp(89));
正在工作
请分别解释所有点。
等价 HighTemp::lessThanTemp
的 lambda 表达式是
(highTemp1, highTemp2) -> {
return highTemp1.lessThanTemp(highTemp2);
}
这是 Java8
名为 Reference to an Instance Method of an Arbitrary Object of a Particular Type
的功能之一
考虑以下示例,
interface FIface<T> {
int testMethod(T a, T b);
}
class Test2 {
private String str;
Test2(String str) {
this.str = str;
}
int ok(Test2 test2) {
System.out.println("Currnet String : "+ this.str);//Refer to t1
System.out.println("Test String : "+test2.str);//Refer to t2
return 0;
}
}
public class Test {
public static <T> int checkCall(T t1, T t2, FIface<T> fiFace) {
//Here Test2 :: ok is equivalent to t1.ok(t2)
return fiFace.testMethod(t1, t2);
}
public static void main(String[] args) {
checkCall(new Test2("a"), new Test2("b"), Test2 :: ok);
}
}
输出
Currnet String : a
Test String : b
注意这里 Test2 :: ok
即使 ok
方法不是静态的,调用也是有效的。
当您为功能接口调用方法 checkCall
时,您仍然有两个参数,即 t1
和 t2
,并且对于该有效的 lambda 表达式,参数可以是 (Test t1, Test t2)
所以你的方法 Test2 :: ok
在这里对调用有效。在内部它是这样工作的 t1.ok(t2)
.
因此,fiFace.testMethod(t1, t2);
将调用方法作为 t1.ok(t2)
首先,我不是专业程序员。我也很难理解所谓的“对特定类型的任意对象的实例方法的引用”我认为这可能对通过 google 搜索来到这里的人有所帮助。
借助lambda表达式,我稍微理解了一点。
在您的代码中 HighTemp::lessThanTemp
作为 Lambda 表达式看起来像 (x,y)->{x.lessThanTemp(y);}
用此 lambda 表达式替换方法引用会产生相同的结果。上面的 Lambda 表达式或方法引用都告诉接口方法要做什么。
当您使用方法引用时,它会告诉接口方法使用给定 class 中的引用方法来执行其功能。因此,如果您将 HighTemp::lessThanTemp
转换为英文单词,它听起来像是“implement the lessThanTemp
method form the class HighTemp
as implementation of the interface function ”。正如您可能已经注意到的那样,return 类型和参数类型应该是兼容的。否则无法实现接口。
我会为您提供另一个简单的示例代码。更多示例有助于理解这个概念。
interface myint{
int returnit(Test t ,int y);
}
class Test{
int x=0;
public Test(int x){
this.x=x;
}
public int addNumbers(int y){
return x+y;
}
public int subtractNumbers(int y){
return x-y;
}
}
public class myclass{
private static void myMethod(Test t,myint inf,int y){
int x=inf.returnit(t, y);
System.out.println(x+"");
}
public static void main(String[] args){
myMethod(new Test(4),Test::addNumbers,7);
myMethod(new Test(4),Test::subtractNumbers,7);
}
}
输出为:
11
-3
这是我能想到的最简单的方法。查看 return 类型和参数类型如何使用上述句型进行匹配。花点时间吧。
这是界面
package learninglambdaexp;
@FunctionalInterface
public interface TempInterface {
public boolean validTemp(Temperature temp);
}
这是class
package learninglambdaexp;
public class Temperature {
private int temp;
public Temperature(int temp) {
this.temp = temp;
}
public boolean isEvenTemp() {
return temp % 2 == 0;
}
public boolean isOddTemp(){
return !isEvenTemp();
}
}
这是 Class 与 Main 方法
package learninglambdaexp;
import java.util.ArrayList;
import java.util.List;
public class AnotherMainClass {
public static void main(String[] args) {
List<Temperature> tempCollection = new ArrayList<>();
tempCollection.add(new Temperature(100));
tempCollection.add(new Temperature(20));
tempCollection.add(new Temperature(30));
tempCollection.add(new Temperature(40));
tempCollection.add(new Temperature(50));
tempCollection.add(new Temperature(60));
tempCollection.add(new Temperature(70));
int k1 = countVariation(tempCollection, Temperature::isEvenTemp);
//int k2 = countVariation(Temperature::lowTemp);
System.out.println(k1);
// System.out.println(k2);
}
private static int countVariation(List<Temperature> tempCollection, TempInterface ti) {
int count = 0;
for (Temperature eachTemp : tempCollection) {
if (ti.validTemp(eachTemp)) { // (eachTemp) -> {return eachTemp.isEvenTemp();};
count++;
}
}
return count;
}
}
一个参数更容易理解
如果我错了,请纠正我,但我对这种类型的方法引用的看法(Reference to an Instance Method of an Arbitrary Object of a Particular Type)是当我们传递一个方法引用时,在本例中传递给 counter 方法,匿名 class 的实例实现了 MyFunc 接口被建造。然后,在这个匿名 class 中,我们覆盖传递两个参数的 func 方法。然后在func方法里面,lessThanTemp方法是这样调用的:
v1.lessThanTemp(v2);
所以对我来说这个概念看起来像这样:
public class Demo {
public static void main(String[] args) {
AnonymousClass an = new AnonymousClass();
System.out.println(an.apply(new SomeClass(3), 4));
}
}
interface SomeInterface {
int apply(SomeClass obj, int n);
}
class SomeClass {
private int n;
SomeClass(int n) {
this.n = n;
}
int add(int n) {
return this.n + n;
}
}
class AnonymousClass implements SomeInterface {
@Override
public int apply(SomeClass o, int n) {
return o.add(n);
}
}
public interface MyFunc<T> {
boolean func(T v1, T v2);
}
public class HighTemp {
private int hTemp;
HighTemp(){
}
public HighTemp(int ht) {
this.hTemp = ht;
}
boolean sameTemp(HighTemp ht2){
return hTemp == ht2.hTemp;
}
boolean lessThanTemp(HighTemp ht2){
return hTemp < ht2.hTemp;
}
}
class InstMethWithObjRef {
static <T> int counter(T[] vals, MyFunc<T> f, T v){
int count = 0;
for (int i = 0; i < vals.length; i++) {
if(f.func(vals[i], v)) count++;
}
return count;
}
public static void main(String[] args) {
int count;
//Create an array of HighTemp objects.
HighTemp[] weekDayHighs = {new HighTemp(89), new HighTemp(82),
new HighTemp(90), new HighTemp(89),
new HighTemp(89), new HighTemp(91),
new HighTemp(84), new HighTemp(83)};
count = counter(weekDayHighs, HighTemp::lessThanTemp,new HighTemp(89));
System.out.println(count);
}
}
请解释如何
boolean sameTemp()
与函数接口中的func()
兼容。sameTemp()
方法在func()
上在功能接口中实现。count = counter(weekDayHighs, HighTemp::sameTemp, new HighTemp(89));
正在工作
请分别解释所有点。
等价 HighTemp::lessThanTemp
的 lambda 表达式是
(highTemp1, highTemp2) -> {
return highTemp1.lessThanTemp(highTemp2);
}
这是 Java8
名为 Reference to an Instance Method of an Arbitrary Object of a Particular Type
考虑以下示例,
interface FIface<T> {
int testMethod(T a, T b);
}
class Test2 {
private String str;
Test2(String str) {
this.str = str;
}
int ok(Test2 test2) {
System.out.println("Currnet String : "+ this.str);//Refer to t1
System.out.println("Test String : "+test2.str);//Refer to t2
return 0;
}
}
public class Test {
public static <T> int checkCall(T t1, T t2, FIface<T> fiFace) {
//Here Test2 :: ok is equivalent to t1.ok(t2)
return fiFace.testMethod(t1, t2);
}
public static void main(String[] args) {
checkCall(new Test2("a"), new Test2("b"), Test2 :: ok);
}
}
输出
Currnet String : a
Test String : b
注意这里 Test2 :: ok
即使 ok
方法不是静态的,调用也是有效的。
当您为功能接口调用方法 checkCall
时,您仍然有两个参数,即 t1
和 t2
,并且对于该有效的 lambda 表达式,参数可以是 (Test t1, Test t2)
所以你的方法 Test2 :: ok
在这里对调用有效。在内部它是这样工作的 t1.ok(t2)
.
因此,fiFace.testMethod(t1, t2);
将调用方法作为 t1.ok(t2)
首先,我不是专业程序员。我也很难理解所谓的“对特定类型的任意对象的实例方法的引用”我认为这可能对通过 google 搜索来到这里的人有所帮助。
借助lambda表达式,我稍微理解了一点。
在您的代码中 HighTemp::lessThanTemp
作为 Lambda 表达式看起来像 (x,y)->{x.lessThanTemp(y);}
用此 lambda 表达式替换方法引用会产生相同的结果。上面的 Lambda 表达式或方法引用都告诉接口方法要做什么。
当您使用方法引用时,它会告诉接口方法使用给定 class 中的引用方法来执行其功能。因此,如果您将 HighTemp::lessThanTemp
转换为英文单词,它听起来像是“implement the lessThanTemp
method form the class HighTemp
as implementation of the interface function ”。正如您可能已经注意到的那样,return 类型和参数类型应该是兼容的。否则无法实现接口。
我会为您提供另一个简单的示例代码。更多示例有助于理解这个概念。
interface myint{
int returnit(Test t ,int y);
}
class Test{
int x=0;
public Test(int x){
this.x=x;
}
public int addNumbers(int y){
return x+y;
}
public int subtractNumbers(int y){
return x-y;
}
}
public class myclass{
private static void myMethod(Test t,myint inf,int y){
int x=inf.returnit(t, y);
System.out.println(x+"");
}
public static void main(String[] args){
myMethod(new Test(4),Test::addNumbers,7);
myMethod(new Test(4),Test::subtractNumbers,7);
}
}
输出为:
11
-3
这是我能想到的最简单的方法。查看 return 类型和参数类型如何使用上述句型进行匹配。花点时间吧。
这是界面
package learninglambdaexp;
@FunctionalInterface
public interface TempInterface {
public boolean validTemp(Temperature temp);
}
这是class
package learninglambdaexp;
public class Temperature {
private int temp;
public Temperature(int temp) {
this.temp = temp;
}
public boolean isEvenTemp() {
return temp % 2 == 0;
}
public boolean isOddTemp(){
return !isEvenTemp();
}
}
这是 Class 与 Main 方法
package learninglambdaexp;
import java.util.ArrayList;
import java.util.List;
public class AnotherMainClass {
public static void main(String[] args) {
List<Temperature> tempCollection = new ArrayList<>();
tempCollection.add(new Temperature(100));
tempCollection.add(new Temperature(20));
tempCollection.add(new Temperature(30));
tempCollection.add(new Temperature(40));
tempCollection.add(new Temperature(50));
tempCollection.add(new Temperature(60));
tempCollection.add(new Temperature(70));
int k1 = countVariation(tempCollection, Temperature::isEvenTemp);
//int k2 = countVariation(Temperature::lowTemp);
System.out.println(k1);
// System.out.println(k2);
}
private static int countVariation(List<Temperature> tempCollection, TempInterface ti) {
int count = 0;
for (Temperature eachTemp : tempCollection) {
if (ti.validTemp(eachTemp)) { // (eachTemp) -> {return eachTemp.isEvenTemp();};
count++;
}
}
return count;
}
}
一个参数更容易理解
如果我错了,请纠正我,但我对这种类型的方法引用的看法(Reference to an Instance Method of an Arbitrary Object of a Particular Type)是当我们传递一个方法引用时,在本例中传递给 counter 方法,匿名 class 的实例实现了 MyFunc 接口被建造。然后,在这个匿名 class 中,我们覆盖传递两个参数的 func 方法。然后在func方法里面,lessThanTemp方法是这样调用的:
v1.lessThanTemp(v2);
所以对我来说这个概念看起来像这样:
public class Demo {
public static void main(String[] args) {
AnonymousClass an = new AnonymousClass();
System.out.println(an.apply(new SomeClass(3), 4));
}
}
interface SomeInterface {
int apply(SomeClass obj, int n);
}
class SomeClass {
private int n;
SomeClass(int n) {
this.n = n;
}
int add(int n) {
return this.n + n;
}
}
class AnonymousClass implements SomeInterface {
@Override
public int apply(SomeClass o, int n) {
return o.add(n);
}
}