Calls to getClass() when using method references

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Calls to getClass() when using method references

Brent Walker
For a function like the following:

public static <A, B> LinkedList<B> flatMap(
  final LinkedList<A> list,
  final Function<A, LinkedList<B>> f) {
  final ArrayList<B> v = new ArrayList<>();

  forEachImpl(list, l -> forEachImpl(f.apply(l), v::add));

  return fromArray(v);
}

Here is the bytecode generated for the lambda at the forEachImpl() (lambda
is in bold above). Function forEachImpl is just a static function.

private static void lambda$flatMap$75(java.util.function.Function,
java.util.ArrayList, java.lang.Object);
    flags: ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC

    Code:
      stack=3, locals=3, args_size=3
         0: aload_0
         1: aload_2
         2: invokeinterface #59,  2           // InterfaceMethod
java/util/function/Function.apply:(Ljava/lang/Object;)Ljava/lang/Object;
         7: checkcast     #6                  // class
DataStructures/LinkedList
        10: aload_1
        11: dup
        *12: invokevirtual #21                 // Method
java/lang/Object.getClass:()Ljava/lang/Class;*
*        15: pop           *
        16: invokedynamic #238,  0            // InvokeDynamic
#51:accept:(Ljava/util/ArrayList;)Ljava/util/function/Consumer;
        21: invokestatic  #1                  // Method
forEachImpl:(LDataStructures/LinkedList;Ljava/util/function/Consumer;)V
        24: return


Can somebody please explain the purpose of the call to virtual method
getClass()?  It looks like we just throw away the result (via a pop) as
soon as that function returns so why do we call it?

Thanks,
Brent

Reply | Threaded
Open this post in threaded view
|

Re: Calls to getClass() when using method references

Remi Forax
On 01/05/2014 12:44 PM, Brent Walker wrote:

> For a function like the following:
>
> public static <A, B> LinkedList<B> flatMap(
>    final LinkedList<A> list,
>    final Function<A, LinkedList<B>> f) {
>    final ArrayList<B> v = new ArrayList<>();
>
>    forEachImpl(list, l -> forEachImpl(f.apply(l), v::add));
>
>    return fromArray(v);
> }
>
> Here is the bytecode generated for the lambda at the forEachImpl() (lambda
> is in bold above). Function forEachImpl is just a static function.
>
> private static void lambda$flatMap$75(java.util.function.Function,
> java.util.ArrayList, java.lang.Object);
>      flags: ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
>
>      Code:
>        stack=3, locals=3, args_size=3
>           0: aload_0
>           1: aload_2
>           2: invokeinterface #59,  2           // InterfaceMethod
> java/util/function/Function.apply:(Ljava/lang/Object;)Ljava/lang/Object;
>           7: checkcast     #6                  // class
> DataStructures/LinkedList
>          10: aload_1
>          11: dup
>          *12: invokevirtual #21                 // Method
> java/lang/Object.getClass:()Ljava/lang/Class;*
> *        15: pop           *
>          16: invokedynamic #238,  0            // InvokeDynamic
> #51:accept:(Ljava/util/ArrayList;)Ljava/util/function/Consumer;
>          21: invokestatic  #1                  // Method
> forEachImpl:(LDataStructures/LinkedList;Ljava/util/function/Consumer;)V
>          24: return
>
>
> Can somebody please explain the purpose of the call to virtual method
> getClass()?  It looks like we just throw away the result (via a pop) as
> soon as that function returns so why do we call it?

It's an idiom uses by javac to do a quick nullcheck,
here the compiler test that v is not null before doing v::add.
All modern Java VMs transform this idiom to a nullcheck (implicit or not).
>
> Thanks,
> Brent
>

cheers,
RĂ©mi