I have a list of student, List<Student>
and I am using javassist-3.9.0.GA jar.
when i am writing list.stream().collect(Collectos.grouping(Student::getCode))
it is giving Caused by: java.io.IOException: invalid constant type: 18
exception. When I change above statement as list.stream().collect(Collectos.grouping(p->p.getCode()))
it works.
Byte code manupulation of p->p.getCode()
and Student::getCode
are not same?
how above two statement is working differently while same javassist is being used?
Summary: I have a class Like:
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();
Now below statement is working fine on javassist-3.9.0.GA jar
Map<String,List<TripDetail>> tripMap=studentList.stream().collect(Collectors.groupingBy(p -> p.getCode()));
but with the same Jar below statement is giving invalid constant type: 18
exception
Map<String,List<TripDetail>> tripMap=studentList.stream().collect(Collectors.groupingBy(Student::getCode));
So as per my knowledge p -> p.getCode()
and Student::getCode
both are same,so either both should give that exception or both should be working.
According to an answer here, Javassist 3.9 doesn't fully support the Java 8 features you're using. Upgrade Javassist, if you can. If not, you're stuck with the p -> p.getCode()
version.
As for the difference between the two syntaxes, p -> p.getCode()
is a lambda expression that creates a new anonymous function invoking getCode()
on its argument. The argument type comes from the functional interface the expression is fulfilling.
Meanwhile, Student::getCode
doesn't create a new function, it's simply a lambda expression that references the existing getCode
method of Student
.
Fundamentally the difference is that p -> p.getCode()
does not belong to anybody, whereas Student::getCode
belongs to the Student
.
I compiled a quick example to see what effect that has on the method invocation. With the p -> p.getCode()
version, this bytecode is produced:
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;
With the Student::getCode
version, you get this:
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;
You can see that the anonymous lambda function is invoked with invokestatic
, while the referenced method is invoked with invokevirtual
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With