I believe that what Mr. LaPaso has reported here is a flat-out bug.
I believe that lines 3 and 4 of the program he presents should
result in a compile-time error. First, JLS 8.4.6.2 clearly states
that Baxter.sm hides Abner.sm in his example. Second, JLS 6.6.2
is pretty clear that Baxter.sm is not accessible within Barney.sm .
Period. Unless the TRC has explicitly addressed this point and
changed the language---and I have no record of that---I believe this
is a JDK bug.
--Guy
Date: Tue, 03 Mar 1998 14:17:26 -0700
From: Tony LaPaso <###@###.###>
MIME-Version: 1.0
To: Guy Steele <###@###.###>
Subject: The Big WHY?
Content-Transfer-Encoding: 7bit
Hello Mr. Steele,
I realize you don't know me and that you're probably very busy. I was
hoping, however, that you might be able to offer a few words of
explanation on something the Java Language Spec does not appear to
address. The issue is really quite simple to explain. Thus far,
however, nobody has been able to offer an explanation as to *why* the
behavior is correct. The most I heard was from James Gosling saying
that it "is correct".
I was hoping that if you had a chance, you could perhaps offer a few
words of explanation as to why the behavior described below is
correct--if indeed it is correct. I *understand* the pattern of the
behavior but the behavior itself does not appear to be addressed
anywhere in the Java Language Specification.
I have the following classes with inheritance as indicated:
Abner
|
+---+---+
| |
Baxter Barney
|
Charlie
Each class is in its own package and has a single method:
protected static void sm();
This method simply prints the name of the class (preceded by the word
'static') (e.g., 'static ABNER').
In addition to the sm() method, the Barney class has an instance method,
'callMe()', as well as data fields for each of the other three classes.
Here's the complete Barney class:
package BarneyPKG;
import AbnerPKG.Abner;
import BaxterPKG.Baxter;
import CharliePKG.Charlie;
public class Barney extends Abner
{
public Abner mySuper; // initialized elsewhere
public Baxter myBrother; // initialized elsewhere
public Charlie mySub; // initialized elsewhere
protected static void sm()
{
System.out.println("static BARNEY");
}
public void callMe()
{
// CALL... OUTPUT...
mySub.sm(); // 1. static BARNEY
Charlie.sm(); // 2. static BARNEY
myBrother.sm(); // 3. static ABNER
Baxter.sm(); // 4. static ABNER
mySuper.sm(); // 5. static ABNER
Abner.sm(); // 6. static ABNER
}
Here's a quote from sec. 6.6.2 of the Java Language Spec.:
"A protected member or constructor of an object may be accessed from
outside the package in which it is declared only by code that is
responsible for the implementation of that object."
Here's another relevant(?) quote from sec. 8.4.6.2 of the Java Language
Spec.:
"If a class declares a static method, then the declaration of that
method is said to hide any and all methods with the same signature in
the superclasses and superinterfaces of the class that would otherwise
be accessible to code in the class."
I can see what is happening in lines 1-6: If a protected static method
is called, the version of the method that gets invoked is the version
that is "common" to both the class making the invocation (in this case,
Barney) and the class whose method is being called (in the case of lines
1-2, Charlie; for lines 3-4, Baxter; for lines 5-6, Abner). For lines
1-2, the common class is Barney; for lines 6-9, its Abner.
Being the purist that I am, I'm somewhat at a loss for *why* this
behavior makes sense. It seems that sec. 6.6.2 is completely irrelevant
since were not dealing with instance methods here (is that correct?).
Yet, "protected" is very definitely coming into play (changing
"protected" to "public" yields different results).
In addition, sec. 8.4.6.2 seems to *contradict* the behavior we're
seeing. Why isn't Baxter.sm() hiding Abner.sm() (as per sec. 8.4.6.2)?
I suppose it *is* hiding Abner.sm() but only if invoked from within
Baxter or a subclass of Baxter. Does sec. 8.4.6.2 only pertain to
non-protected static methods?
Would you be able to either point me to a section(s) from The Spec. that
explains this behavior? Or could you possibly offer some rationale for
this behavior? Does the Java Language Spec. even address this issue?
I'm sure you're busy and I honestly appreciate any explanation you can
offer.
Thanks very much.
--
+========================================+
| Tony LaPaso -- ###@###.### |
| |
| Cyclone Software Corporation |
| Scottsdale, Arizona USA |
+----------------------------------------+
| Be good. |
+========================================+
I believe that lines 3 and 4 of the program he presents should
result in a compile-time error. First, JLS 8.4.6.2 clearly states
that Baxter.sm hides Abner.sm in his example. Second, JLS 6.6.2
is pretty clear that Baxter.sm is not accessible within Barney.sm .
Period. Unless the TRC has explicitly addressed this point and
changed the language---and I have no record of that---I believe this
is a JDK bug.
--Guy
Date: Tue, 03 Mar 1998 14:17:26 -0700
From: Tony LaPaso <###@###.###>
MIME-Version: 1.0
To: Guy Steele <###@###.###>
Subject: The Big WHY?
Content-Transfer-Encoding: 7bit
Hello Mr. Steele,
I realize you don't know me and that you're probably very busy. I was
hoping, however, that you might be able to offer a few words of
explanation on something the Java Language Spec does not appear to
address. The issue is really quite simple to explain. Thus far,
however, nobody has been able to offer an explanation as to *why* the
behavior is correct. The most I heard was from James Gosling saying
that it "is correct".
I was hoping that if you had a chance, you could perhaps offer a few
words of explanation as to why the behavior described below is
correct--if indeed it is correct. I *understand* the pattern of the
behavior but the behavior itself does not appear to be addressed
anywhere in the Java Language Specification.
I have the following classes with inheritance as indicated:
Abner
|
+---+---+
| |
Baxter Barney
|
Charlie
Each class is in its own package and has a single method:
protected static void sm();
This method simply prints the name of the class (preceded by the word
'static') (e.g., 'static ABNER').
In addition to the sm() method, the Barney class has an instance method,
'callMe()', as well as data fields for each of the other three classes.
Here's the complete Barney class:
package BarneyPKG;
import AbnerPKG.Abner;
import BaxterPKG.Baxter;
import CharliePKG.Charlie;
public class Barney extends Abner
{
public Abner mySuper; // initialized elsewhere
public Baxter myBrother; // initialized elsewhere
public Charlie mySub; // initialized elsewhere
protected static void sm()
{
System.out.println("static BARNEY");
}
public void callMe()
{
// CALL... OUTPUT...
mySub.sm(); // 1. static BARNEY
Charlie.sm(); // 2. static BARNEY
myBrother.sm(); // 3. static ABNER
Baxter.sm(); // 4. static ABNER
mySuper.sm(); // 5. static ABNER
Abner.sm(); // 6. static ABNER
}
Here's a quote from sec. 6.6.2 of the Java Language Spec.:
"A protected member or constructor of an object may be accessed from
outside the package in which it is declared only by code that is
responsible for the implementation of that object."
Here's another relevant(?) quote from sec. 8.4.6.2 of the Java Language
Spec.:
"If a class declares a static method, then the declaration of that
method is said to hide any and all methods with the same signature in
the superclasses and superinterfaces of the class that would otherwise
be accessible to code in the class."
I can see what is happening in lines 1-6: If a protected static method
is called, the version of the method that gets invoked is the version
that is "common" to both the class making the invocation (in this case,
Barney) and the class whose method is being called (in the case of lines
1-2, Charlie; for lines 3-4, Baxter; for lines 5-6, Abner). For lines
1-2, the common class is Barney; for lines 6-9, its Abner.
Being the purist that I am, I'm somewhat at a loss for *why* this
behavior makes sense. It seems that sec. 6.6.2 is completely irrelevant
since were not dealing with instance methods here (is that correct?).
Yet, "protected" is very definitely coming into play (changing
"protected" to "public" yields different results).
In addition, sec. 8.4.6.2 seems to *contradict* the behavior we're
seeing. Why isn't Baxter.sm() hiding Abner.sm() (as per sec. 8.4.6.2)?
I suppose it *is* hiding Abner.sm() but only if invoked from within
Baxter or a subclass of Baxter. Does sec. 8.4.6.2 only pertain to
non-protected static methods?
Would you be able to either point me to a section(s) from The Spec. that
explains this behavior? Or could you possibly offer some rationale for
this behavior? Does the Java Language Spec. even address this issue?
I'm sure you're busy and I honestly appreciate any explanation you can
offer.
Thanks very much.
--
+========================================+
| Tony LaPaso -- ###@###.### |
| |
| Cyclone Software Corporation |
| Scottsdale, Arizona USA |
+----------------------------------------+
| Be good. |
+========================================+
- relates to
-
JDK-4033907 protected access not implemented correctly for static protected fields/methods
- Closed