Nis*_*hat 5 java javassist java-8 java-stream
我有一个学生名单,List<Student>
我正在使用 javassist-3.9.0.GA jar。
当我写list.stream().collect(Collectos.grouping(Student::getCode))
它时,它给出了Caused by: java.io.IOException: invalid constant type: 18
例外。当我更改上述语句list.stream().collect(Collectos.grouping(p->p.getCode()))
时。
字节码manupulationp->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;
}
}
Run Code Online (Sandbox Code Playgroud)
List<Student> studentList=getStudentList();
现在下面的语句在 javassist-3.9.0.GA jar 上运行良好
Map<String,List<TripDetail>> tripMap=studentList.stream().collect(Collectors.groupingBy(p -> p.getCode()));
Run Code Online (Sandbox Code Playgroud)
但在下面的声明中使用相同的 Jar 给出了invalid constant type: 18
例外
Map<String,List<TripDetail>> tripMap=studentList.stream().collect(Collectors.groupingBy(Student::getCode));
Run Code Online (Sandbox Code Playgroud)
所以据我所知p -> p.getCode()
,Student::getCode
两者都是相同的,所以要么两者都应该给出例外,要么两者都应该工作。
根据此处的答案,Javassist 3.9 不完全支持您正在使用的 Java 8 功能。如果可以的话,升级 Javassist。如果没有,你就会被这个p -> p.getCode()
版本困住。
两种语法之间的区别在于p -> p.getCode()
lambda 表达式,它创建一个调用getCode()
其参数的新匿名函数。参数类型来自表达式所实现的函数接口。
同时,Student::getCode
并没有创建一个新函数,它只是一个引用现有getCode
方法的lambda 表达式Student
。
从根本上来说,区别在于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;
Run Code Online (Sandbox Code Playgroud)
有了这个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;
Run Code Online (Sandbox Code Playgroud)
您可以看到匿名 lambda 函数是通过 调用的invokestatic
,而引用的方法是通过 调用的invokevirtual
。
归档时间: |
|
查看次数: |
1125 次 |
最近记录: |