It is well-known that both anonymous inner classes and capturing lambdas have implicitly added private fields in some cases. For instance-field anonymous class it is a reference to the outer class instance and for local and static anonymous instances nothing. But local-instance lambda differs: it has a field of captured variable's type. If in the end they are used the same way, why do they have this difference? Why cannot local lambda be built in the exact copy of local anonymous class?
UPD:
A little sample
Class to test anonymous class's fields
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));
}
}
}
Output:
-- local anonymous class --
- constructors -
field.AnonymousExample$3()
- fields -
-- instance anonymous class --
- constructors -
field.AnonymousExample$1(field.AnonymousExample)
- fields -
field name: this$0,
field type: class field.AnonymousExample,
field value: field.AnonymousExample@79fc0f2f
-- static member anonymous class --
- constructors -
field.AnonymousExample$2()
- fields -
Class to test capturing lambda's fields
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());
System.out.println("\n-- instance capturing lambda --");
CapturingLambdaExample em = new CapturingLambdaExample();
print(em.instanceRunnable.getClass());
System.out.println("\n-- static capturing lambda --");
print(staticRunnable.getClass());
}
public static void print(Class<?> c) 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.getName(),
field.getType());
}
}
}
Output:
-- local capturing lambda --
- constructors -
private field.CapturingLambdaExample$$Lambda$15/0x0000000840065440(int)
- fields -
field name: arg$1,
field type: int,
-- instance capturing lambda --
- constructors -
private field.CapturingLambdaExample$$Lambda$25/0x0000000840068840(field.CapturingLambdaExample)
- fields -
field name: arg$1,
field type: class field.CapturingLambdaExample,
-- static capturing lambda --
- constructors -
private field.CapturingLambdaExample$$Lambda$14/0x0000000840064c40()
- fields -