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