-
Bug
-
Resolution: Fixed
-
P5
-
1.3.0
-
1.4
-
generic
-
generic
-
Verified
------------------------------
I hope my suggestions are useful.
Norbert Schirmer
Personal Remark:
I only got to these sophisticated examples, which show some flaws in the Java
Language Specification, due to the pedantic precision the theorem prover
Isabelle enforces when I formally modeled the Java package/access concept.
For such a large and complex specification as the Java Language Specification,
the imprecise informal document is not strong enough to show up the subtle
interaction between the class and the package concept. Therefor I think
formal methods should be applied rigorously during the design of a new
language. Maybe then the package/access concept would be a simpler one.
---- Glossary --------------------------------------------------------------
I want to clarify some notions of the Java Language Specification and
this bug report that may be confusing:
<<<<<<<<<<<<<<<<<<< From the Java Language Specification >>>>>>>>>>>>>>>
"code is responsible for the implementation"
"class is involved in the implementation"
A class is involved in the implementation of the class itself and of all
its subclasses. Therefore the code in the body of a class is responsible
for the implementation of the class itself and of all its subclasses.
"class declares a member"
The member is actually declared in the body of this class. It is not just
inherited.
"member of a class", "method of a class"
The member/method can be inherited or actually be declared in the body of
the class.
"member of class C accessible from body of class S"
"accessible to code"
This notion is used to to determine whether access to a member of class C
is allowed from body of class S or not. "Accessible to code" is an imprecise
abbreviation for this. Note that possibly three different classes
and their packages influence the behavior:
- class C and its package
- the class declaring the member and its package
- the class S and its package
<<<<<<<<<<<<<<<<<<< New in this bug report >>>>>>>>>>>>>>>>>>>>>>>>>
"method of class C accessible from body of class S"
This is a specialized version of "member of class C accessible..." for
methods. It substitutes the general version in case the member actually is
a method.
"member of class C accessible for inheritance in subclass of C"
This notion is used to determine whether the member can be inherited by
a subclass of C or not. Also here possibly three different classes and their
packages influence the behavior:
- class C and its package
- the class declaring the member and its package
- the subclass of C and its package
----------------------------------------------------------------------------
(Review ID: 130209)
======================================================================
Name: boT120536 Date: 08/17/2001
java version "1.3.0"
Java(TM) 2 Runtime Environment, Standard Edition (build Blackdown-1.3.0-FCS)
Java HotSpot(TM) Client VM (build Blackdown-1.3.0-FCS, mixed mode)
but also:
java version "1.1.6"
Hello,
I have encountered some further inconsistency in the package/access
concept as described in the Java Language Specification (Second Edition),
besides the one I already reported in the bug report with bug id: 4485402.
The JDK does not implement the specified behavior. However the implemented
semantics seems to be the intended one. I want to describe two problems:
1) Throughout the Java Language Specification the same notion of
accessibility is used both to describe the legal access to a member and
to determine which members are inherited. This is wrong. We have to
distinguish both cases.
2) Accessibility of members is defined uniformly for all kinds of members
(class, interface, field, or method). This is wrong. Due to
overriding methods actually have weaker access restrictions.
I will explain these problems in detail and give some examples. I also
want to propose some new definitions which hopefully will eliminate these
problems. I have added a small glossary at the end, to clarify some notions
which sound very similar and may be confusing.
1) Accessibility for inheritance
-----------------------------
Let's first have a look at the definition of inheritance:
----------- Java Language Specification-------------------------------------
8.4.6 Inheritance, Overriding, and Hiding
A class inherits from its direct superclass and direct superinterfaces
all the non-private methods (whether abstract or not) of the superclass and
superinterfaces that are accessible to code in the class and are neither
overridden (8.4.6.1) nor hidden (8.4.6.2) by a declaration in the class.
----------------------------------------------------------------------------
I want to focus on the case, where no new declaration of the member is given,
so that overriding or hiding does not occur. In that case
all the accessible members are inherited.
(By the way, the distinction between non-private and accessible members to
describe inheritance seems to be completely unnecessary, since private
members aren't accessible in a subclass. So it would suffice to talk only
about accessible members here.)
This is what the Java Language Specification says about accessibility:
----------- Java Language Specification-------------------------------------
6.6.1 Determining Accessibility
A package is always accessible. If a class or interface type is declared
public, then it may be accessed by any code, provided that the compilation
unit (7.3) in which it is declared is observable. If a top level class or
interface type is not declared public, then it may be accessed only from
within the package in which it is declared. An array type is accessible
if and only if its element type is accessible.
A member (class, interface, field, or method) of a reference
(class, interface, or array) type or a constructor of a class type is
accessible only if the type is accessible and the member or constructor
is declared to permit access:
If the member or constructor is declared public, then access is
permitted.
All members of interfaces are implicitly public.
Otherwise, if the member or constructor is declared protected,
then access is permitted only when one of the following is true:
Access to the member or constructor occurs from within the package
containing the class in which the protected member or constructor is
declared.
Access is correct as described in 6.6.2.
Otherwise, if the member or constructor is declared private, then access
is permitted if and only if it occurs within the body of the top level
class (7.6) that encloses the declaration of the member.
Otherwise, we say there is default access, which is permitted only when
the access occurs from within the package in which the type is declared.
----------------------------------------------------------------------------
Let me first point out a detail that can easily be overseen. For default
(package) access and for protected access, access from within the package is
allowed. But the package referred to is not necessarily the package of the
class we currently look at. The Java Language Specification refers to the
package of the class "declaring" the member.
This is crucial since an inherited member can be declared in a different
package.
Let me now focus on the critical case were the inconsistency occurs. Its the
sub-case of protected access described in an extra section (6.6.2). The member
is declared protected and is accessed from outside the package:
----------- Java Language Specification-------------------------------------
6.6.2 Details on protected Access
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.
6.6.2.1 Access to a protected Member
Let C be the class in which a protected member m is declared. Access is
permitted only within the body of a subclass S of C. In addition, if Id
denotes an instance field or instance method, then:
If the access is by a qualified name Q.Id, where Q is an ExpressionName,
then the access is permitted if and only if the type of the expression Q is S
or a subclass of S.
If the access is by a field access expression E.Id, where E is a
Primary expression, or by a method invocation expression E.Id(. . .), where
E is a Primary expression, then the access is permitted if and only if the
type of E is S or a subclass of S.
----------------------------------------------------------------------------
Since it is hard to understand what exactly "responsible for implementation"
means there is an example in the specification to clarify this aspect:
----------- Java Language Specification-------------------------------------
6.6.7 Example: protected Fields, Methods, and Constructors
Consider this example, where the points package declares:
package points;
public class Point {
protected int x, y;
void warp(threePoint.Point3d a) {
if (a.z > 0) // compile-time error: cannot access a.z
a.delta(this);
}
}
and the threePoint package declares:
package threePoint;
import points.Point;
public class Point3d extends Point {
protected int z;
public void delta(Point p) {
p.x += this.x; // compile-time error: cannot access p.x
p.y += this.y; // compile-time error: cannot access p.y
}
public void delta3d(Point3d q) {
q.x += this.x;
q.y += this.y;
q.z += this.z;
}
}
which defines a class Point3d. A compile-time error occurs in the method delta
here: it cannot access the protected members x and y of its parameter p,
because while Point3d (the class in which the references to fields x and y
occur) is a subclass of Point (the class in which x and y are declared), it
is not involved in the implementation of a Point (the type of the
parameter p). The method delta3d can access the protected members of its
parameter q, because the class Point3d is a subclass of Point and is
involved in the implementation of a Point3d.
----------------------------------------------------------------------------
So a class is involved in the implementation of the class itself and of all
its subclasses. Or from a more operational point of view, if a class has
a protected member (independent if this member is declared in the class
itself or is inherited from a superclass) the class can access this member
from itself and from all of its subclasses. So on the other hand, if the
protected member is inherited from a superclass the class is not allowed to
access the member in the superclass. Let me illustrate this with a small
example:
Let A, B, C, D be classes. B extends A; C extends B; D extends C;
A declares a protected member m. The member m is inherited by all the
subclasses B, C and D.
Lets focus on class B. Class B is is allowed to access member m from
Objects of class B, C or D but not from Objects of class A.
| --> B is allowed to access m from B, C, D but not from A
|
A B C D
Lets return to the example of Point and Point3d.
The crucial point is that the fields x and y of the superclass Point are not
accessible in the subclass Point3d in the expressions p.x respectively p.y
(inside the method delta). Since p has type Point, Point.x and Point.y are
not accessible from Point3d.
But with this in mind there is no reason why the members x and y of the
superclass Point should be inherited by the subclass Point3d. Since
accessibility of Point.x and Point.y is required for inheritance
(refer to 8.4.6, cited above).
But the intended behavior of a protected member is, that it is inherited by
a subclass. Therefore to describe inheritance appropriately we must take a
different definition of accessibility as a basis for inheritance.
Accessible for inheritance:
A member declared in class A is "accessible for inheritance" in a subclass C
if
Either
1) a) class A is accessible from class C and
b) the member of A is declared protected or public or if it is declared
with default (package) access, the package of class C is the same as
the package of class A. (If the member of A is declared with private
access it is not accessible for inheritance)
2) There is a intermediate class B (distinct from A and C), B is subclass of
A and C is subclass of B and all the following conditions hold:
a) class B is accessible from class C and
b) the member of class A is accessible for inheritance in class B (so it
is indeed inherited by class B if no overriding or hiding occurs) and
c) the member of A is declared protected or public or if it is declared
with default (package) access, the package of class C is the same as
the package of class B. (If the member of A is declared with private
access it is not accessible for inheritance)
Condition 1 defines the obvious intended semantics for inheritance.
All public and protected members are inherited and members with default
(package) access are only inherited inside the package.
Condition 2 is designed for the case that class A is not accessible
directly (Condition 1 a) in class C, for example if class A is non public and
class C is in a different package than A, there has to be an intermediate
public class B which makes the members of A visible to C. This is in analogy
to my correction of overriding proposed in bug report 4485402.
This definition "accessible for inheritance" should replace the notion
"accessible to code" in 8.4.6.
2) Special accessibility for methods
---------------------------------
Due to overriding there are some cases where methods are accessible but other
members (especially fields) would not be accessible. This has to be added
in the accessibility definition.
Consider the following example:
package APackage;
public class A
{
protected void foo() {}
}
package BPackage;
public class B extends A
{
protected void foo() {}
protected void bar() {}
}
package APackage;
import BPackage.B;
public class C
{
public void call()
{
B b = new B();
b.foo(); // allowed
b.bar(); // not allowed
}
}
Class B is a subclass of A and is declared in a different package than A.
The class C is declared in the same package as A. All methods of A
respectively B are declared with protected access. Since class C is neither
subclass of A nor B it intuitively can only access the protected members of
A but not those of B, since C and A are in the same package
(refer to 6.6.1 cited above).
We can't access B.bar() from C since B is in a different package than C.
But C is allowed to access B.foo(). Why?
Imagine that B would not override A.foo(). Then it would inherit foo() from
class A. Since we are allowed to access A.foo() from C we expect that we can
access the inherited version of foo() in B, too, because B.foo() is not
freshly declared in B but inherited from A, where it is actually declared.
The notion of accessibility of a protected member in this case is
described with respect to the declaring class not the class inheriting the
member.
But when B overrides foo(), B freshly declares foo(). So strictly referring
to the specification foo() should not be accessible from C as this is the
case for method bar(). But intuitively we expect a method to be accessible
if it overrides an accessible method.
So we have to extend the general definition of accessibility for all members
with a special case for methods. Whenever we want to express a
"method is accessible from..." in the Java Language Definition we should
take this specialized version not the general one:
A method m of a class C is accessible from a class S if either
1) The method is accessible due to existing definition of accessibility
(Java Language Specification 6.6.1) or
2) All the following conditions hold:
a) The class C is accessible from S
b) there is an old method m' of a class A with
i) C is a subclass of A and
ii) method m overrides method m' and
iii) method m' of class A is accessible from class S
Note that m must not necessarily be declared in class C (it can also be
inherited from a superclass) and that m' must not necessarily be declared in
class A (it can also be inherited from a superclass). This is crucial, since
the declaring classes of m respectively m' must not necessarily be
accessible from S (e.g. if they are non public and reside in a different
package than S).
Since I proposed a different definition of overriding in bug report 4485402
what exactly do I refer to in case 2 a ii?
If we take the definition of "accessible for inheritance" - I just introduced
above - as a basis for overriding (instead of the ordinary accessibility
notion) we can take the original definition of overriding of the
Java Language Specification. The problematic case, that a method of an
unaccessible class becomes accessible through to inheritance is already
captured in case 2 of "accessible for inheritance".
----------- Java Language Specification---(modified)------------------------
8.4.6.1 Overriding (by Instance Methods)
An instance method m1 declared in a class C overrides another method
with the same signature, m2, declared in class A if both
1. C is a subclass of A.
2. Either
a) m2 is non-private and "accessible for inheritance" from C, or
b) m1 overrides a method m3, m3 distinct from m1, m3 distinct from m2,
such that m3 overrides m2.
----------------------------------------------
I hope my suggestions are useful.
Norbert Schirmer
Personal Remark:
I only got to these sophisticated examples, which show some flaws in the Java
Language Specification, due to the pedantic precision the theorem prover
Isabelle enforces when I formally modeled the Java package/access concept.
For such a large and complex specification as the Java Language Specification,
the imprecise informal document is not strong enough to show up the subtle
interaction between the class and the package concept. Therefor I think
formal methods should be applied rigorously during the design of a new
language. Maybe then the package/access concept would be a simpler one.
---- Glossary --------------------------------------------------------------
I want to clarify some notions of the Java Language Specification and
this bug report that may be confusing:
<<<<<<<<<<<<<<<<<<< From the Java Language Specification >>>>>>>>>>>>>>>
"code is responsible for the implementation"
"class is involved in the implementation"
A class is involved in the implementation of the class itself and of all
its subclasses. Therefore the code in the body of a class is responsible
for the implementation of the class itself and of all its subclasses.
"class declares a member"
The member is actually declared in the body of this class. It is not just
inherited.
"member of a class", "method of a class"
The member/method can be inherited or actually be declared in the body of
the class.
"member of class C accessible from body of class S"
"accessible to code"
This notion is used to to determine whether access to a member of class C
is allowed from body of class S or not. "Accessible to code" is an imprecise
abbreviation for this. Note that possibly three different classes
and their packages influence the behavior:
- class C and its package
- the class declaring the member and its package
- the class S and its package
<<<<<<<<<<<<<<<<<<< New in this bug report >>>>>>>>>>>>>>>>>>>>>>>>>
"method of class C accessible from body of class S"
This is a specialized version of "member of class C accessible..." for
methods. It substitutes the general version in case the member actually is
a method.
"member of class C accessible for inheritance in subclass of C"
This notion is used to determine whether the member can be inherited by
a subclass of C or not. Also here possibly three different classes and their
packages influence the behavior:
- class C and its package
- the class declaring the member and its package
- the subclass of C and its package
----------------------------------------------------------------------------
(Review ID: 130209)
======================================================================
Name: boT120536 Date: 08/17/2001
java version "1.3.0"
Java(TM) 2 Runtime Environment, Standard Edition (build Blackdown-1.3.0-FCS)
Java HotSpot(TM) Client VM (build Blackdown-1.3.0-FCS, mixed mode)
but also:
java version "1.1.6"
Hello,
I have encountered some further inconsistency in the package/access
concept as described in the Java Language Specification (Second Edition),
besides the one I already reported in the bug report with bug id: 4485402.
The JDK does not implement the specified behavior. However the implemented
semantics seems to be the intended one. I want to describe two problems:
1) Throughout the Java Language Specification the same notion of
accessibility is used both to describe the legal access to a member and
to determine which members are inherited. This is wrong. We have to
distinguish both cases.
2) Accessibility of members is defined uniformly for all kinds of members
(class, interface, field, or method). This is wrong. Due to
overriding methods actually have weaker access restrictions.
I will explain these problems in detail and give some examples. I also
want to propose some new definitions which hopefully will eliminate these
problems. I have added a small glossary at the end, to clarify some notions
which sound very similar and may be confusing.
1) Accessibility for inheritance
-----------------------------
Let's first have a look at the definition of inheritance:
----------- Java Language Specification-------------------------------------
8.4.6 Inheritance, Overriding, and Hiding
A class inherits from its direct superclass and direct superinterfaces
all the non-private methods (whether abstract or not) of the superclass and
superinterfaces that are accessible to code in the class and are neither
overridden (8.4.6.1) nor hidden (8.4.6.2) by a declaration in the class.
----------------------------------------------------------------------------
I want to focus on the case, where no new declaration of the member is given,
so that overriding or hiding does not occur. In that case
all the accessible members are inherited.
(By the way, the distinction between non-private and accessible members to
describe inheritance seems to be completely unnecessary, since private
members aren't accessible in a subclass. So it would suffice to talk only
about accessible members here.)
This is what the Java Language Specification says about accessibility:
----------- Java Language Specification-------------------------------------
6.6.1 Determining Accessibility
A package is always accessible. If a class or interface type is declared
public, then it may be accessed by any code, provided that the compilation
unit (7.3) in which it is declared is observable. If a top level class or
interface type is not declared public, then it may be accessed only from
within the package in which it is declared. An array type is accessible
if and only if its element type is accessible.
A member (class, interface, field, or method) of a reference
(class, interface, or array) type or a constructor of a class type is
accessible only if the type is accessible and the member or constructor
is declared to permit access:
If the member or constructor is declared public, then access is
permitted.
All members of interfaces are implicitly public.
Otherwise, if the member or constructor is declared protected,
then access is permitted only when one of the following is true:
Access to the member or constructor occurs from within the package
containing the class in which the protected member or constructor is
declared.
Access is correct as described in 6.6.2.
Otherwise, if the member or constructor is declared private, then access
is permitted if and only if it occurs within the body of the top level
class (7.6) that encloses the declaration of the member.
Otherwise, we say there is default access, which is permitted only when
the access occurs from within the package in which the type is declared.
----------------------------------------------------------------------------
Let me first point out a detail that can easily be overseen. For default
(package) access and for protected access, access from within the package is
allowed. But the package referred to is not necessarily the package of the
class we currently look at. The Java Language Specification refers to the
package of the class "declaring" the member.
This is crucial since an inherited member can be declared in a different
package.
Let me now focus on the critical case were the inconsistency occurs. Its the
sub-case of protected access described in an extra section (6.6.2). The member
is declared protected and is accessed from outside the package:
----------- Java Language Specification-------------------------------------
6.6.2 Details on protected Access
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.
6.6.2.1 Access to a protected Member
Let C be the class in which a protected member m is declared. Access is
permitted only within the body of a subclass S of C. In addition, if Id
denotes an instance field or instance method, then:
If the access is by a qualified name Q.Id, where Q is an ExpressionName,
then the access is permitted if and only if the type of the expression Q is S
or a subclass of S.
If the access is by a field access expression E.Id, where E is a
Primary expression, or by a method invocation expression E.Id(. . .), where
E is a Primary expression, then the access is permitted if and only if the
type of E is S or a subclass of S.
----------------------------------------------------------------------------
Since it is hard to understand what exactly "responsible for implementation"
means there is an example in the specification to clarify this aspect:
----------- Java Language Specification-------------------------------------
6.6.7 Example: protected Fields, Methods, and Constructors
Consider this example, where the points package declares:
package points;
public class Point {
protected int x, y;
void warp(threePoint.Point3d a) {
if (a.z > 0) // compile-time error: cannot access a.z
a.delta(this);
}
}
and the threePoint package declares:
package threePoint;
import points.Point;
public class Point3d extends Point {
protected int z;
public void delta(Point p) {
p.x += this.x; // compile-time error: cannot access p.x
p.y += this.y; // compile-time error: cannot access p.y
}
public void delta3d(Point3d q) {
q.x += this.x;
q.y += this.y;
q.z += this.z;
}
}
which defines a class Point3d. A compile-time error occurs in the method delta
here: it cannot access the protected members x and y of its parameter p,
because while Point3d (the class in which the references to fields x and y
occur) is a subclass of Point (the class in which x and y are declared), it
is not involved in the implementation of a Point (the type of the
parameter p). The method delta3d can access the protected members of its
parameter q, because the class Point3d is a subclass of Point and is
involved in the implementation of a Point3d.
----------------------------------------------------------------------------
So a class is involved in the implementation of the class itself and of all
its subclasses. Or from a more operational point of view, if a class has
a protected member (independent if this member is declared in the class
itself or is inherited from a superclass) the class can access this member
from itself and from all of its subclasses. So on the other hand, if the
protected member is inherited from a superclass the class is not allowed to
access the member in the superclass. Let me illustrate this with a small
example:
Let A, B, C, D be classes. B extends A; C extends B; D extends C;
A declares a protected member m. The member m is inherited by all the
subclasses B, C and D.
Lets focus on class B. Class B is is allowed to access member m from
Objects of class B, C or D but not from Objects of class A.
| --> B is allowed to access m from B, C, D but not from A
|
A B C D
Lets return to the example of Point and Point3d.
The crucial point is that the fields x and y of the superclass Point are not
accessible in the subclass Point3d in the expressions p.x respectively p.y
(inside the method delta). Since p has type Point, Point.x and Point.y are
not accessible from Point3d.
But with this in mind there is no reason why the members x and y of the
superclass Point should be inherited by the subclass Point3d. Since
accessibility of Point.x and Point.y is required for inheritance
(refer to 8.4.6, cited above).
But the intended behavior of a protected member is, that it is inherited by
a subclass. Therefore to describe inheritance appropriately we must take a
different definition of accessibility as a basis for inheritance.
Accessible for inheritance:
A member declared in class A is "accessible for inheritance" in a subclass C
if
Either
1) a) class A is accessible from class C and
b) the member of A is declared protected or public or if it is declared
with default (package) access, the package of class C is the same as
the package of class A. (If the member of A is declared with private
access it is not accessible for inheritance)
2) There is a intermediate class B (distinct from A and C), B is subclass of
A and C is subclass of B and all the following conditions hold:
a) class B is accessible from class C and
b) the member of class A is accessible for inheritance in class B (so it
is indeed inherited by class B if no overriding or hiding occurs) and
c) the member of A is declared protected or public or if it is declared
with default (package) access, the package of class C is the same as
the package of class B. (If the member of A is declared with private
access it is not accessible for inheritance)
Condition 1 defines the obvious intended semantics for inheritance.
All public and protected members are inherited and members with default
(package) access are only inherited inside the package.
Condition 2 is designed for the case that class A is not accessible
directly (Condition 1 a) in class C, for example if class A is non public and
class C is in a different package than A, there has to be an intermediate
public class B which makes the members of A visible to C. This is in analogy
to my correction of overriding proposed in bug report 4485402.
This definition "accessible for inheritance" should replace the notion
"accessible to code" in 8.4.6.
2) Special accessibility for methods
---------------------------------
Due to overriding there are some cases where methods are accessible but other
members (especially fields) would not be accessible. This has to be added
in the accessibility definition.
Consider the following example:
package APackage;
public class A
{
protected void foo() {}
}
package BPackage;
public class B extends A
{
protected void foo() {}
protected void bar() {}
}
package APackage;
import BPackage.B;
public class C
{
public void call()
{
B b = new B();
b.foo(); // allowed
b.bar(); // not allowed
}
}
Class B is a subclass of A and is declared in a different package than A.
The class C is declared in the same package as A. All methods of A
respectively B are declared with protected access. Since class C is neither
subclass of A nor B it intuitively can only access the protected members of
A but not those of B, since C and A are in the same package
(refer to 6.6.1 cited above).
We can't access B.bar() from C since B is in a different package than C.
But C is allowed to access B.foo(). Why?
Imagine that B would not override A.foo(). Then it would inherit foo() from
class A. Since we are allowed to access A.foo() from C we expect that we can
access the inherited version of foo() in B, too, because B.foo() is not
freshly declared in B but inherited from A, where it is actually declared.
The notion of accessibility of a protected member in this case is
described with respect to the declaring class not the class inheriting the
member.
But when B overrides foo(), B freshly declares foo(). So strictly referring
to the specification foo() should not be accessible from C as this is the
case for method bar(). But intuitively we expect a method to be accessible
if it overrides an accessible method.
So we have to extend the general definition of accessibility for all members
with a special case for methods. Whenever we want to express a
"method is accessible from..." in the Java Language Definition we should
take this specialized version not the general one:
A method m of a class C is accessible from a class S if either
1) The method is accessible due to existing definition of accessibility
(Java Language Specification 6.6.1) or
2) All the following conditions hold:
a) The class C is accessible from S
b) there is an old method m' of a class A with
i) C is a subclass of A and
ii) method m overrides method m' and
iii) method m' of class A is accessible from class S
Note that m must not necessarily be declared in class C (it can also be
inherited from a superclass) and that m' must not necessarily be declared in
class A (it can also be inherited from a superclass). This is crucial, since
the declaring classes of m respectively m' must not necessarily be
accessible from S (e.g. if they are non public and reside in a different
package than S).
Since I proposed a different definition of overriding in bug report 4485402
what exactly do I refer to in case 2 a ii?
If we take the definition of "accessible for inheritance" - I just introduced
above - as a basis for overriding (instead of the ordinary accessibility
notion) we can take the original definition of overriding of the
Java Language Specification. The problematic case, that a method of an
unaccessible class becomes accessible through to inheritance is already
captured in case 2 of "accessible for inheritance".
----------- Java Language Specification---(modified)------------------------
8.4.6.1 Overriding (by Instance Methods)
An instance method m1 declared in a class C overrides another method
with the same signature, m2, declared in class A if both
1. C is a subclass of A.
2. Either
a) m2 is non-private and "accessible for inheritance" from C, or
b) m1 overrides a method m3, m3 distinct from m1, m3 distinct from m2,
such that m3 overrides m2.
----------------------------------------------
- relates to
-
JDK-4642788 8.4.6.1 Overriding is unclear.
- Closed
-
JDK-4485402 Wrong implementation of definition of "override"
- Closed