adding default method changes interface initialization order?
Alex Buckley
alex.buckley at oracle.com
Tue Apr 22 21:23:55 UTC 2014
// Adding lambda-dev; follow-ups to both lists please.
Default methods are not specified to cause any change in interface
initialization. In principle the body of a default method can execute
without the declaring interface having been initialized; if the body
should touch a static field of the interface, then the interface must
immediately be initialized.
However, that behavior might be a surprise. So surprising, in fact, that
HotSpot seems to be cautiously initializing superinterfaces in advance
of the default method ever being invoked. JSR 335 people should comment
on this. Are all superinterfaces initialized, or just those with default
methods?
In addition, if the default method body invokes a static method of the
interface, then initialization must occur - yet JLS8 12.4.1 does not
require it ("T is a class and a static method declared by T is
invoked.") That's a straight spec bug - but note that specifying
superinterface initialization due to default methods will make it moot.
Alex
On 4/22/2014 1:24 PM, Stuart Marks wrote:
> Hi all,
>
> It seems like the presence of a default method in an interface will
> change the timing of when that interface is initialized.
>
> Interface initialization is covered by JLS 12.4.1 [1]. Example 12.4.1-3
> illustrates this:
>
> interface I {
> int i = 1, ii = Test.out("ii", 2);
> }
> interface J extends I {
> int j = Test.out("j", 3), jj = Test.out("jj", 4);
> }
> interface K extends J {
> int k = Test.out("k", 5);
> }
> class Test {
> public static void main(String[] args) {
> System.out.println(J.i);
> System.out.println(K.j);
> }
> static int out(String s, int i) {
> System.out.println(s + "=" + i);
> return i;
> }
> }
>
> The expected output is:
>
> 1
> j=3
> jj=4
> 3
>
> Indeed, I get the expected output for the example as it stands. However,
> if a default method is added to interface I, the behavior of the program
> changes. Consider:
>
> interface I {
> int i = 1, ii = Test.out("ii", 2);
> default void method() { } // causes initialization!
> }
>
> The output changes to:
>
> 1
> ii=2
> j=3
> jj=4
> 3
>
> That is, the "ii=2" line indicates that interface I has now been
> initialized where it hadn't been before. The mere presence of a default
> method seems to trigger the change, even if the default method is never
> called, referenced, or overridden.
>
> Is this a bug?
>
> (Hat tip to Sotirios Delimanolis for asking this on StackOverflow. [2])
>
> s'marks
>
>
> [1] http://docs.oracle.com/javase/specs/jls/se8/html/jls-12.html#jls-12.4.1
>
> [2]
> http://stackoverflow.com/questions/23096084/when-is-an-interface-with-a-default-method-initialized
>
>
>
> s'marks
More information about the lambda-dev
mailing list