Filter funktioniert in Stream nicht #314

Closed
opened 2024-04-06 12:59:55 +00:00 by i21023 · 0 comments
Collaborator

Die Filter Funktion funktioniert in Streams aktuell nicht richtig.

Beispiel

Code

//Foo.java
import java.lang.Integer;
import java.util.List;
import java.util.ArrayList;
import java.util.stream.Stream;
import java.util.function.Predicate;
import java.util.function.Function;
import java.util.stream.Collectors;

class Foo{
    List<Integer> convert(List<Integer> in){
        return in.stream().filter(x -> x>5).collect(Collectors.toList());
    }
}

Der Code kompiliert zwar, wirft aber einen Fehler zur Laufzeit.

Wenn ich die Methode mithilfe einer der Hilfsklasse Main.java aufrufe, fliegt folgender Fehler:

//Main.java
import java.util.ArrayList;
import java.util.List;
class Main{
    public static void main(String[] args) {
        System.out.println(new Foo().convert(new ArrayList<Integer>(List.of(1,2,3,4,5,6,7,8,9))));
    }
}
Exception in thread "main" java.lang.AbstractMethodError: Receiver class Foo$$Lambda/0x00007c0403000c10 does not define or inherit an implementation of the resolved method 'abstract boolean test(java.lang.Object)' of interface java.util.function.Predicate.
        at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:193)
        at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1709)
        at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:556)
        at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:546)
        at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
        at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:265)
        at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:702)
        at Foo.convert(Unknown Source)
        at Main.main(Main.java:8)

Ich denke dass das Problem auch hier wieder an den primitiven Datentypen liegt.
Der von Java-TX generierte Bytecode der Lambda Funktion sieht folgendermaßen aus:

//Java-TX Bytecode
java.lang.Boolean lambda$0(java.lang.Integer);
    descriptor: (Ljava/lang/Integer;)Ljava/lang/Boolean;
    flags: (0x0000)
    Code:
      stack=2, locals=2, args_size=2
         0: aload_1
         1: invokevirtual #26                 // Method java/lang/Integer.intValue:()I
         4: ldc           #27                 // int 5
         6: if_icmpgt     13
         9: iconst_0
        10: goto          14
        13: iconst_1
        14: invokestatic  #33                 // Method java/lang/Boolean.valueOf:(Z)Ljava/lang/Boolean;
        17: areturn
      StackMapTable: number_of_entries = 2
        frame_type = 13 /* same */
        frame_type = 64 /* same_locals_1_stack_item */
          stack = [ int ]
    Signature: #20                          // (Ljava/lang/Integer;)Ljava/lang/Boolean;

Dazu im Vergleich der von javac generierte Code für den Lambda Ausdruck:

//Javac Bytecode
  private static boolean lambda$convert$0(java.lang.Integer);
    descriptor: (Ljava/lang/Integer;)Z
    flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
    Code:
      stack=2, locals=1, args_size=1
         0: aload_0
         1: invokevirtual #33                 // Method java/lang/Integer.intValue:()I
         4: iconst_5
         5: if_icmple     12
         8: iconst_1
         9: goto          13
        12: iconst_0
        13: ireturn
      LineNumberTable:
        line 11: 0
      StackMapTable: number_of_entries = 2
        frame_type = 12 /* same */
        frame_type = 64 /* same_locals_1_stack_item */
          stack = [ int ]

Man sieht dass Java-TX im Gegensatz zu Javac mit dem Rückgabewert java.lang.Boolean arbeitet, ich denke dass dadurch die test Funktion im Predicate Interface nicht korrekt überschrieben wird, da sie mit dem primitiven Typ boolean als Rückgabe definiert ist.

@FunctionalInterface
public interface Predicate<T> {
   boolean test(T var1);
}
Die Filter Funktion funktioniert in Streams aktuell nicht richtig. ### Beispiel **Code** ```java //Foo.java import java.lang.Integer; import java.util.List; import java.util.ArrayList; import java.util.stream.Stream; import java.util.function.Predicate; import java.util.function.Function; import java.util.stream.Collectors; class Foo{ List<Integer> convert(List<Integer> in){ return in.stream().filter(x -> x>5).collect(Collectors.toList()); } } ``` Der Code kompiliert zwar, wirft aber einen Fehler zur Laufzeit. Wenn ich die Methode mithilfe einer der Hilfsklasse **Main.java** aufrufe, fliegt folgender Fehler: ```java //Main.java import java.util.ArrayList; import java.util.List; class Main{ public static void main(String[] args) { System.out.println(new Foo().convert(new ArrayList<Integer>(List.of(1,2,3,4,5,6,7,8,9)))); } } ``` ``` Exception in thread "main" java.lang.AbstractMethodError: Receiver class Foo$$Lambda/0x00007c0403000c10 does not define or inherit an implementation of the resolved method 'abstract boolean test(java.lang.Object)' of interface java.util.function.Predicate. at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:193) at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1709) at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:556) at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:546) at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921) at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:265) at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:702) at Foo.convert(Unknown Source) at Main.main(Main.java:8) ``` Ich denke dass das Problem auch hier wieder an den primitiven Datentypen liegt. Der von Java-TX generierte Bytecode der Lambda Funktion sieht folgendermaßen aus: ``` //Java-TX Bytecode java.lang.Boolean lambda$0(java.lang.Integer); descriptor: (Ljava/lang/Integer;)Ljava/lang/Boolean; flags: (0x0000) Code: stack=2, locals=2, args_size=2 0: aload_1 1: invokevirtual #26 // Method java/lang/Integer.intValue:()I 4: ldc #27 // int 5 6: if_icmpgt 13 9: iconst_0 10: goto 14 13: iconst_1 14: invokestatic #33 // Method java/lang/Boolean.valueOf:(Z)Ljava/lang/Boolean; 17: areturn StackMapTable: number_of_entries = 2 frame_type = 13 /* same */ frame_type = 64 /* same_locals_1_stack_item */ stack = [ int ] Signature: #20 // (Ljava/lang/Integer;)Ljava/lang/Boolean; ``` Dazu im Vergleich der von javac generierte Code für den Lambda Ausdruck: ``` //Javac Bytecode private static boolean lambda$convert$0(java.lang.Integer); descriptor: (Ljava/lang/Integer;)Z flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC Code: stack=2, locals=1, args_size=1 0: aload_0 1: invokevirtual #33 // Method java/lang/Integer.intValue:()I 4: iconst_5 5: if_icmple 12 8: iconst_1 9: goto 13 12: iconst_0 13: ireturn LineNumberTable: line 11: 0 StackMapTable: number_of_entries = 2 frame_type = 12 /* same */ frame_type = 64 /* same_locals_1_stack_item */ stack = [ int ] ``` Man sieht dass Java-TX im Gegensatz zu Javac mit dem Rückgabewert java.lang.Boolean arbeitet, ich denke dass dadurch die `test` Funktion im Predicate Interface nicht korrekt überschrieben wird, da sie mit dem primitiven Typ `boolean` als Rückgabe definiert ist. ```java @FunctionalInterface public interface Predicate<T> { boolean test(T var1); } ```
dholle was assigned by pl 2024-04-07 09:49:28 +00:00
dholle referenced this issue from a commit 2024-04-09 12:59:36 +00:00
Sign in to join this conversation.
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: JavaTX/JavaCompilerCore#314
No description provided.