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