gpt4 book ai didi

java 8,使用相同的 javassist 时,Lambda 表达式的工作方式不同

转载 作者:搜寻专家 更新时间:2023-11-01 03:19:06 26 4
gpt4 key购买 nike

我有一份学生名单,List<Student>我正在使用 javassist-3.9.0.GA jar。

当我写list.stream().collect(Collectos.grouping(Student::getCode))时它正在给 Caused by: java.io.IOException: invalid constant type: 18异常(exception)。当我将上述语句更改为 list.stream().collect(Collectos.grouping(p->p.getCode()))它有效。

p->p.getCode() 的字节码操作和 Student::getCode不一样吗?

当使用相同的 javassist 时,以上两个语句的工作方式有何不同?

总结:我有一个类像:

class Student{

private String code;
private String name;


public String getCode(){
return code;
}
public void setCode(){
this.code=code;
}

public String getName(){
return name;
}
public void setName(String name){
this.name=name;
}
}

List<Student> studentList=getStudentList();

现在下面的语句在 javassist-3.9.0.GA jar 上工作正常

Map<String,List<TripDetail>> tripMap=studentList.stream().collect(Collectors.groupingBy(p -> p.getCode()));

但使用相同的 Jar,下面的语句给出了 invalid constant type: 18异常

Map<String,List<TripDetail>> tripMap=studentList.stream().collect(Collectors.groupingBy(Student::getCode));

据我所知p -> p.getCode()Student::getCode两者相同,因此要么两者都应该给出该异常,要么两者都应该工作。

最佳答案

根据一个答案here ,Javassist 3.9 不完全支持您正在使用的 Java 8 功能。如果可以,请升级 Javassist。否则,您将无法使用 p -> p.getCode() 版本。

至于这两种语法之间的区别,p -> p.getCode() 是一个 lambda 表达式,它创建一个新的匿名函数调用 getCode()争论。参数类型来自表达式正在实现的功能接口(interface)。

与此同时,Student::getCode 不会创建新函数,它只是一个引用 Student 的现有 getCode 方法的 lambda 表达式>.

根本的区别在于 p -> p.getCode() 不属于任何人,而 Student::getCode 属于 Student

我编译了一个快速示例以查看对方法调用有何影响。使用 p -> p.getCode() 版本,生成此字节码:

SourceFile: "LambdaExampleAnonymous.java"
BootstrapMethods:
0: #51 invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
Method arguments:
#52 (Ljava/lang/Object;)Ljava/lang/Object;
#55 invokestatic example/LambdaExampleAnonymous.lambda$0:(Lexample/Student;)Ljava/lang/String;
#56 (Lexample/Student;)Ljava/lang/String;

使用 Student::getCode 版本,您会得到:

SourceFile: "LambdaExampleReference.java"
BootstrapMethods:
0: #44 invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
Method arguments:
#45 (Ljava/lang/Object;)Ljava/lang/Object;
#50 invokevirtual example/Student.getCode:()Ljava/lang/String;
#52 (Lexample/Student;)Ljava/lang/String;

可以看到匿名lambda函数是用invokestatic调用的,而引用的方法是用invokevirtual调用的。

关于java 8,使用相同的 javassist 时,Lambda 表达式的工作方式不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36673714/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com