Protected variable access inside Lambda blocks

Mark Mahieu markmahieu at gmail.com
Sat Nov 13 19:15:17 PST 2010


Hmm, actually I think there might be a slight wrinkle to watch out for in the current code - if my understanding is correct, then this example should print the result of calling toString() on the instance of 'Lexical':

	class Lexical {

		Lexical() {
			Runnable r = #{ 
				System.out.println(toString());
			};
			r.run();
		}

		public static void main(String[] args) {
			new Lexical();
		}
	}

However, it's calling the Runnable's toString() instead (note the $1):

	$ java Lexical
	Lexical$1 at 3a3ee284

Many other cases do seem to work as I'd expect though, as will the above example if Lexical is made to override toString().


There's also an issue with 'this'...

	class NoSuchField {

		NoSuchField() {
			Runnable r = #{ Object o = this; };
			r.run();
		}

		public static void main(String[] args) {
			new NoSuchField();
		}
	}

... which compiles but throws a NoSuchFieldError when run:

	$ java NoSuchField
	Exception in thread "main" java.lang.NoSuchFieldError: this
	        at NoSuchField$1.run(NoSuchField.java:4)
	        at NoSuchField.<init>(NoSuchField.java:5)
	        at NoSuchField.main(NoSuchField.java:9)


Finally, calling getClass() in a lambda expression causes an AssertionError at compile time:

	class GetClass {
		Runnable r = #{ getClass(); };
	}

	$ javac GetClass.java
	...
	java.lang.AssertionError
	        at com.sun.tools.javac.code.Types.rank(Types.java:2974)
	        at com.sun.tools.javac.code.Types.rank(Types.java:2946)
	        at com.sun.tools.javac.code.Symbol$TypeSymbol.precedes(Symbol.java:574)
	        at com.sun.tools.javac.code.Types.union(Types.java:3108)
	        at com.sun.tools.javac.code.Types.glb(Types.java:3370)
	        at com.sun.tools.javac.code.Types.capture(Types.java:3620)
	        at com.sun.tools.javac.comp.Attr.capture(Attr.java:3812)
	        at com.sun.tools.javac.comp.Attr.visitApply(Attr.java:1565)
	        at com.sun.tools.javac.tree.JCTree$JCMethodInvocation.accept(JCTree.java:1344)
		...

Mark



On 14 Nov 2010, at 00:17, Arul Dhesiaseelan wrote:

> Thanks Mark and Peter for the clarification.
> 
> -Arul
> 
> On Sat, Nov 13, 2010 at 1:30 PM, Peter Levart <peter.levart at gmail.com> wrote:
> On Saturday, November 13, 2010 08:28:15 pm Arul Dhesiaseelan wrote:
> > Hi,
> >
> > I am trying to access a protected final defined in my SAM type from within
> > a Lambda block, but it fails with "cannot find symbol" compile error with
> > the prototype.
> >
> > Here is a simple test:
> >
> > public class ProtectedAccess {
> >     public static abstract class LambdaAccess<T> {
> >         protected static final String DEFAULT = "DEFAULT";
> >         public abstract T block();
> >     }
> >
> >     public static void main(String... args) throws Exception {
> >         LambdaAccess<String> lambdaAccess = #{
> >             return DEFAULT;//compile error: unable to access this protected
> > constant
> >         };
> >         lambdaAccess.block();
> >
> >         LambdaAccess<String> anonymousAccess = new LambdaAccess<String>() {
> >             public String block () {
> >                 return DEFAULT;//works just fine in case of anonymous types
> >             }
> >         };
> >         anonymousAccess.block();
> >     }
> >
> > }
> >
> > I am not sure if this is a limitation or if I am doing something wrong
> > here.
> >
> > -Arul
> 
> As of 15.10.2010, the lambdas are lexically scoped (see:
> http://cr.openjdk.java.net/~briangoetz/lambda/lambda-state-3.html). In other words, code inside
> lambda sees only the symbols as the code immediately outside the lambda expression.
> 
> Peter
> 
> 
> 
> 



More information about the lambda-dev mailing list