Questionable compilation failure

Peter Levart peter.levart at gmail.com
Thu Sep 19 23:58:06 PDT 2013


On 09/20/2013 12:51 AM, Remi Forax wrote:
> On 09/20/2013 12:11 AM, Peter Levart wrote:
>>
>> On 09/18/2013 06:34 PM, Remi Forax wrote:
>>> On 09/18/2013 06:18 PM, Millies, Sebastian wrote:
>>>> Hello there,
>>>>
>>>> on my Windows 7 (64bit) box, the following does not compile with 
>>>> the developer preview build (b 106). Should it?
>>>>
>>>> import java.util.function.Supplier;
>>>>
>>>> public class SupplierTest {
>>>>
>>>>       class Concrete<T> implements Supplier<Concrete<T>> {
>>>>           @Override
>>>>           public Concrete<T> get() {
>>>>               return this;
>>>>           }
>>>>       }
>>>>
>>>>       interface Test  {
>>>>           default void doSomething() {
>>>>                new Concrete<String>();   // <-----
>>>>           }
>>>>       }
>>>>
>>>> }
>>>>
>>>> The error message is:
>>>>
>>>> \SupplierTest.java:16: error: non-static variable this cannot be 
>>>> referenced from a static context
>>>> new Concrete<String>();
>>>> ^
>>>>
>>>> However, a default method implementation is not static, or is it? 
>>>> (Perhaps it's just the error
>>>> message that's confusing me.)
>>> It's maybe a bug, at least the error message is misleading.
>>
>
> Hi Peter,
>
>> I think it's not a bug, but a consequence of the fact that nested 
>> interfaces are by default static.
>
> no, it's not.
>
>>
>> public class SupplierTest {
>>     interface Test {
>> ...
>>
>> actually means:
>>
>> public class SupplierTest {
>>     static interface Test {
>>
>
> An interface inside a class is always a static inner interface,
> but that's not the point here, Test is static with respect to 
> SupplierTest but inside Test you can still have instance method (here 
> a default method) that access to this.
>
> By example, this compiles :
> interface Foo {
>   class A {
>      void m() {
>         System.out.println(this);
>      }
>   }
> }
> even if A is implicitly static.
>
>>
>> It can't be any other way, since interfaces don't have state. 
>
> First you don't need to have state to access to this, you can have 
> object without state that have methods.
> Moreover, even if interfaces don't have state but you can have access 
> to 'this' inside an instance method (a default method) of an interface 
> because when you call the instance method, yu know that there is an 
> instance of a class that implement that interface.
>
>> Non-static nested (inner) classes always have implicit state - the 
>> captured reference to outer instance.
>>
>>
>> Regards, Peter
>
> And to come back to the error message, Eclipse error message is more 
> clear:
> "No enclosing instance of type SupplierTest is accessible. Must 
> qualify the allocation with an enclosing instance of type SupplierTest 
> (e.g. x.new A() where x is an instance of SupplierTest)."

I agree that Eclipse is more clear and I don't object your explanation, 
but I think Sebastian was surprised because the following code:

public class SupplierTest {

     class Concrete<T> implements Supplier<Concrete<T>> {
         @Override
         public Concrete<T> get() {
             return this;
         }
     }

     class Test  {
         void doSomething() {
             new Concrete<String>();   // <-----
         }
     }
}


...does compile. You see, there's no explicit reference to 
SupplierTest.this. before constructor of Concrete. And If you change the 
above to:


public class SupplierTest {

     class Concrete<T> implements Supplier<Concrete<T>> {
         @Override
         public Concrete<T> get() {
             return this;
         }
     }

*static* class Test  {
         void doSomething() {
             new Concrete<String>();   // <-----
         }
     }
}


...you get the same message from javac as with nested interface/default 
method.


Regards, Peter

>
> cheers,
> Rémi
>



More information about the lambda-dev mailing list