Close

Java - Implicit Outer Class reference in Anonymous classes and Lambdas

[Updated: Apr 25, 2018, Created: Apr 25, 2018]

In last example, we saw how an implicit reference of the outer class is added to the inner classes. In these examples, we will see how implicit fields/constructor arguments are added in case of anonymous classes and capturing lambdas.

Examples

Anonymous Classes

public class AnonymousExample {
    private Runnable instanceRunnable = new Runnable() {
        @Override
        public void run() { }
    };

    private static Runnable staticRunnable = new Runnable() {
        @Override
        public void run() { }
    };

    public static void main(String[] args) throws IllegalAccessException {
        Runnable localRunnable = new Runnable() {
            @Override
            public void run() { }
        };
        System.out.println("-- local anonymous class --");
        print(localRunnable.getClass(), localRunnable);

        System.out.println("\n-- instance anonymous class --");
        AnonymousExample em = new AnonymousExample();
        print(em.instanceRunnable.getClass(), em.instanceRunnable);

        System.out.println("\n-- static member anonymous class --");
        print(staticRunnable.getClass(), staticRunnable);
    }

    public static void print(Class<?> c, Object instance) throws IllegalAccessException {
        System.out.println("- constructors -");
        for (Constructor<?> constructor : c.getDeclaredConstructors()) {
            System.out.println(constructor.toGenericString());
        }
        System.out.println("- fields -");
        for (Field field : c.getDeclaredFields()) {
            System.out.printf(" field name: %s,%n field type: %s,%n field value: %s%n",
                    field.getName(),
                    field.getType(),
                    field.get(instance));
        }
    }
}
-- local anonymous class --
- constructors -
com.logicbig.example.AnonymousExample$3()
- fields -

-- instance anonymous class --
- constructors -
com.logicbig.example.AnonymousExample$1(com.logicbig.example.AnonymousExample)
- fields -
field name: this$0,
field type: class com.logicbig.example.AnonymousExample,
field value: com.logicbig.example.AnonymousExample@6e0be858

-- static member anonymous class --
- constructors -
com.logicbig.example.AnonymousExample$2()
- fields -

The above output shows that only in case of 'instance' anonymous class, an implicit outer class instance field were added by the compiler

Non-Capturing Lambdas

public class LambdaExample {
    private Runnable instanceRunnable = () -> { };

    private static Runnable staticRunnable = () -> { };

    public static void main(String[] args) throws IllegalAccessException {
        Runnable localRunnable = () -> { };
        System.out.println("-- local lambda --");
        print(localRunnable.getClass(), localRunnable);

        System.out.println("\n-- class instance lambda --");
        LambdaExample em = new LambdaExample();
        print(em.instanceRunnable.getClass(), em.instanceRunnable);

        System.out.println("\n-- class static lambda --");
        print(staticRunnable.getClass(), staticRunnable);
    }
    .............
}
-- local lambda --
- constructors -
private com.logicbig.example.LambdaExample$$Lambda$2/931919113()
- fields -

-- class instance lambda --
- constructors -
private com.logicbig.example.LambdaExample$$Lambda$3/1607521710()
- fields -

-- class static lambda --
- constructors -
private com.logicbig.example.LambdaExample$$Lambda$1/81628611()
- fields -

No extract field or constructor argument was added in case of non-capturing lambdas.

Capturing Lambdas

public class CapturingLambdaExample {
    private int x = 10;
    private static int y = 20;

    private Runnable instanceRunnable = () -> { System.out.println(x);};
    private static Runnable staticRunnable = () -> { System.out.println(y);};

    public static void main(String[] args) throws IllegalAccessException {
        int z = 20;//effectively final
        Runnable localRunnable = () -> { System.out.println(z);};
        System.out.println("-- local capturing lambda --");
        print(localRunnable.getClass(), localRunnable);

        System.out.println("\n-- instance capturing lambda --");
        CapturingLambdaExample em = new CapturingLambdaExample();
        print(em.instanceRunnable.getClass(), em.instanceRunnable);

        System.out.println("\n-- static capturing lambda --");
        print(staticRunnable.getClass(), staticRunnable);
    }
    .............
}
-- local capturing lambda --
- constructors -
private com.logicbig.example.CapturingLambdaExample$$Lambda$2/1607521710(int)
- fields -
field name: arg$1,
field type: int,
field value: 20

-- instance capturing lambda --
- constructors -
private com.logicbig.example.CapturingLambdaExample$$Lambda$3/1329552164(com.logicbig.example.CapturingLambdaExample)
- fields -
field name: arg$1,
field type: class com.logicbig.example.CapturingLambdaExample,
field value: com.logicbig.example.CapturingLambdaExample@7b23ec81

-- static capturing lambda --
- constructors -
private com.logicbig.example.CapturingLambdaExample$$Lambda$1/81628611()
- fields -

As seen above, in case of the lambda which is capturing local variable (effectively final), the same variable type field (int) and constructor argument were added. In case of instance level lambda which is capturing other instance variable, the outer class field was implicitly added. Nothing was implicitly added in case of static capturing lambda.

Example Project

Dependencies and Technologies Used:

  • JDK 1.8
  • Maven 3.3.9

Java Implicit Outer Class Reference Select All Download
  • anonymous-outer-class-implicit-reference
    • src
      • main
        • java
          • com
            • logicbig
              • example
                • AnonymousExample.java

    See Also