Inner classes are allowed to be specified in 'uses' statement
Peter Levart
peter.levart at gmail.com
Mon Apr 11 20:20:07 UTC 2016
Hi Georgiy,
It turns out that an inner class can be extended by a non-inner class.
See JLS "8.8.7.1. Explicit Constructor Invocations":
"Qualified superclass constructor invocations begin with a Primary
expression or an ExpressionName. They allow a subclass constructor to
explicitly specify the newly created object's immediately enclosing
instance with respect to the direct superclass (§8.1.3). This may be
necessary when the superclass is an inner class."
I've never done that in code before, but it seems it works:
public class Outer {
public class Inner {}
}
public class Sub extends Outer.Inner {
Sub() {
new Outer().super();
}
}
...so, it seems that a service interface can be an inner class.
Regards, Peter
On 04/11/2016 12:42 PM, Georgiy Rakov wrote:
> Hi Peter,
>
> On 04.04.2016 11:39, Peter Levart wrote:
>> Hi Georgiy,
>>
>> On 04/01/2016 04:52 PM, Georgiy Rakov wrote:
>>> Hello,
>>>
>>> currently inner classes are allowed to be specified in 'uses'
>>> statement, for instance following code is compiled successfully by
>>> JDKb111 javac:
>>>
>>> a/module-info.java:
>>> module a {
>>> uses pkg.Outer.Inner;
>>> }
>>>
>>> a/pkg/Outer.java:
>>> package pkg;
>>> public class Outer{ public class Inner{} }
>>>
>>> Spec doesn't prevent it either. However in 1.1.3
>>> <http://cr.openjdk.java.net/%7Emr/jigsaw/spec/lang-vm.html> it
>>> prevents implementations specified in 'provides' statement to be
>>> inner classes. According to my understanding inner class cannot be
>>> extended by non-inner class, for instance "public class Impl extends
>>> Outer.Inner { } " would cause:
>>>
>>> error: an enclosing instance
>>> that contains Outer.Inner is required
>>> class Implem extends Outer.Inner {}
>>> ^
>>> 1 error
>>>
>>> So could you please tell what is the purpose of allowing inner
>>> classes to be specified in 'uses' statement, there seem to be no way
>>> to create its implementation. Should it be prohibited by spec?
>>>
>>> The minimized testcase is attached; in order to run it please:
>>> 1. unzip attached archive on Windows machine;
>>> 2. rename test12\test_bat to test12\test.bat;
>>> 3. modify test.bat by changing JDK_HOME variable to point to your
>>> JDK installation;
>>> 4. run test.bat.
>>>
>>> Thank you,
>>> Georgiy.
>>
>> Not only in 'uses' statement. It would be impossible to specify them
>> in 'provides ... with ...' statement as implementation classes too as
>> they by definition can't be instantiated without an outer instance
>> (their constructors always contain an implicit parameter - the outer
>> instance). What does compiler say for such case?
>>
>> a/module-info.java:
>> module a {
>> exports pkg;
>> provides pkg.Service with pkg.impl.Outer.Inner;
>> }
>>
>> a/pkg/Service.java:
>> package pkg;
>> public interface Service {}
>>
>> a/pkg/impl/Outer.java:
>> package pkg.impl;
>> public class Outer { public class Inner implements pkg.Service { } }
>>
>>
> For such case jdk9b113 javac says:
>
> a\module-info.java:3: error: the service implementation is an
> inner class: Outer.Inner
> provides pkg.Service with pkg.impl.Outer.Inner;
> ^
> 1 error
>
> As I've already said this is according to spec:
>
> It is a compile-time error if the service implementation named by
> the |with|clause of a |provides|statement is |abstract|, or is not
> |public|, or does not have a |public|no-args constructor, or is
> *an inner class* (JLS 8.1.3).
>
> But spec doesn't prevent service interfaces to be inner classes.
I see. But that could be deduced since service implementations is either
the same class or a subtype of service interface (a subclass of or a
class implementing service interface). And a subclass of an inner class is
>
> Thanks,
> Georgiy.
>> Regards, Peter
>>
>
More information about the jigsaw-dev
mailing list