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

我有一份学生名单,List< Student>

我正在使用
javassist-3.9.0.GA jar.

当我写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;
   }
}

列表与LT;学生> studentList = getStudentList();

现在,下面的语句在javassist-3.9.0.GA jar上运行正常

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

但是使用相同的Jar下面的语句给出了无效的常量类型: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().参数类型来自表达式正在实现的功能接口.

同时,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;

您可以看到使用invokestatic调用匿名lambda函数,而使用invokevirtual调用引用的方法.

点赞