Dark corners of the JLS: static methods, hiding, and bytecode

O

Owen Jacobson

Quoth the JLS:

-----
8.4.8.2 Hiding (by Class Methods)

If a class declares a static method m, then the declaration m is said
to hide any method m', where the signature of m is a subsignature
(§8.4.2) of the signature of m', in the superclasses and
superinterfaces of the class that would otherwise be accessible to
code in the class. A compile-time error occurs if a static method
hides an instance method.
-----

In practical terms, this means the following code is legal:

class A1 {
static A1 foo () { return null; }
}

class B1 extends A1 {
static B1 foo () { return null; }
}

since B1 is compatible with A1, but the following code is not legal:

class A2 {
static A2 bar () { return null; }
}

class B2 extends A2 {
static int bar () { return 0; }
}

since int is not compatible with A2.

This is somewhat surprising, when you consider that static methods are
not subject to virtual dispatch and therefore do not override each
other.

Examining the runtime behaviour (and the bytecode) for the following
is enlightening, however:

class A3 {
static String testMethod () { return "In A3.testMethod."; }
}

class B3 extends A3 {
}

class C3 {
public static void main (String[] args) {
System.out.println (B3.testMethod ());
}
}

Compiling these three classes and running
$ java C3
prints
In A3.testMethod.
as expected. However, if we modify B3 as follows

class B3 extends A3 {
static String testMethod () { return "In B3.testMethod."; }
}

and recompile *only* B3, rerunning C3 produces this:
In B3.testMethod.

even though C3 has not been recompiled.

Examining C3's bytecode reveals that the initial compile produced

3: invokestatic #3; //Method B3.testMethod:()Ljava/lang/String;

for the line corresponding to the statement B3.testMethod(); -- that
is, the class referenced in the method call is B3, not A3 (where the
method is actually defined).

I *think* the justification for this feature, where static methods are
partially resolved at runtime, is to allow code like the above to be
updated without necessarily recompiling C3. However, given how
fragile this is and given how Java behaves in the presence of constant
expressions at compile time, it's a little surprising.

The more you know...

-o
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top