簡體   English   中英

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

[英]java 8,Lambda Expressions working differently while same javassist is being used

我有一個學生List<Student>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()))它可以工作。

p->p.getCode()Student::getCode p->p.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<Student> studentList=getStudentList();

現在,下面的語句在javassist-3.9.0.GA jar上運行正常

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

但是使用相同的Jar下面的語句給出了invalid constant type: 18異常

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

所以根據我的知識, p -> p.getCode()Student::getCode p -> p.getCode()都是相同的,所以要么兩者都應該給出異常,要么兩者都應該有效。

根據這里的答案,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;

你可以看到,匿名lambda函數被調用, invokestatic ,而引用的方法與調用invokevirtual

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM