Java8中,Lambda表达式在使用相同的javassist时工作方式不同

Java8中,Lambda表达式在使用相同的javassist时工作方式不同,java,java-8,java-stream,javassist,Java,Java 8,Java Stream,Javassist,我有一份学生名单,list 我正在使用javassist-3.9.0.gajar 当我在写list.stream().collect(Collectos.grouping(Student::getCode)) 它正在给出由以下原因引起的:java.io.IOException:无效常量类型:18异常。当我将上面的语句更改为list.stream().collect(Collectos.grouping(p->p.getCode())时,它就工作了 p->p.getCode()和Student::

我有一份学生名单,
list
我正在使用javassist-3.9.0.gajar

当我在写
list.stream().collect(Collectos.grouping(Student::getCode))
它正在给出由以下原因引起的
:java.io.IOException:无效常量类型:18
异常。当我将上面的语句更改为
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 studentList=getStudentList()

下面的语句在javassist-3.9.0.gajar上运行良好

Map<String,List<TripDetail>> tripMap=studentList.stream().collect(Collectors.groupingBy(p -> p.getCode()));
据我所知,
p->p.getCode()
Student::getCode
都是相同的,所以要么两者都应该给出例外,要么两者都应该工作。

根据答案,Javassist 3.9不完全支持您正在使用的Java8功能。如果可以,请升级Javassist。如果没有,您就只能使用
p->p.getCode()
版本

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

同时,
Student::getCode
并没有创建新函数,它只是一个lambda表达式,引用了
Student
的现有
getCode
方法

从根本上说,区别在于
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
调用的。您的意思是
groupingBy
?是的,很抱歉,我没有编写准确的语法,
Collectors
->
Collectors
grouping
->
groupingBy
。你能提供一个Misha吗,我已经更新了这个问题。
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;