Static method access dilemma and proposal: @NotInherited

Brian Goetz brian.goetz at oracle.com
Thu Jun 27 11:36:47 PDT 2013


I got what you were saying.  What I was telling you is that our 
compatibility goals are higher than that, and that at the very least it 
would take probably 2-3 major versions, even if we were willing to do 
this.  We have a very limited budget for this kind of incompatibility; 
we want to spend it where it will provide the most payoff.  Here, our 
excuse is pretty lame: "we think Java should have been designed the 
other way, so we're changing it."  That's just a silly thing to spend 
our incompatibility budget on.  (And I agree with you that this language 
feature was a mistake.)



On 6/27/2013 2:32 PM, Paul Benedict wrote:
> Brian, if you're focus is 99/100% compatibility, I guess it won't work.
> However, if you loosen the requirements, it should be possible to
> overcome the compatibility reasons with this plan:
>
> For class files <= 52.0, the JVM will resolve static method inheritance.
> Otherwise, when code is recompiled for JDK 9+ (>= 53.0), static method
> inheritence will be rejected. This should be made even easier with the
> deprecation of --source/--target (JEP 182). If absolute source
> compatibility is necessary, the source compatibility could be controlled
> by another JVM option.
>
>
> On Thu, Jun 27, 2013 at 1:14 PM, Brian Goetz <brian.goetz at oracle.com
> <mailto:brian.goetz at oracle.com>> wrote:
>
>     Total agreement that it was a mistake to have them be inheritable.
>     Static methods in interfaces don't have this defect.  (And we took a
>     hit for that inconsistency.)  Unfortunately what you suggest for 9
>     is impractical for compatibility reasons.
>
>     Overall I like Stephen's proposal here (except I am not convinced
>     that it is suitable for an annotation, but that's a pretty
>     superficial aspect of it.)  Anything that moves us towards being
>     able to fix this problem over time is good.
>
>
>     On 6/27/2013 1:50 PM, Paul Benedict wrote:
>
>         Stephen, it's an interesting idea. Bikeshed moment.... At the
>         cost of
>         having to recompile future code, I'd rather wish to have static
>         methods on
>         classes not be inheritable in JDK 9 and onward. Then the same
>         behavior can
>         be predictable across classes or interfaces. Fixing a bad
>         language design
>         is probably better than patching things up with @NotInherited.
>
>
>         On Thu, Jun 27, 2013 at 12:20 PM, Stephen Colebourne
>         <scolebourne at joda.org <mailto:scolebourne at joda.org>>wrote:
>
>             The addition of static methods on interfaces has given
>             developers a
>             new very useful tool. However, it has also produced a dliemma.
>
>             A static method on a class is accessible/"inherited" by
>             subclasses.
>             Thus SubClass.foo() is just as good as SuperClass.foo() for
>             accessing
>             the static method defined on SuperClass. By contrast, with
>             static
>             methods on interfaces, this is not possible - a static
>             method on an
>             interface is not "inherited" (a Good Thing).
>
>             The dliemma, from JSR-310
>             (https://github.com/ThreeTen/__threeten/issues/321
>             <https://github.com/ThreeTen/threeten/issues/321>), is that
>             I _really_
>             want to avoid the inheritance of static methods from one
>             abstract
>             class (Chronology), as the methods make no sense at all to
>             be called
>             on the subclasses, and in fact they may cause bugs. Thus,
>             the new
>             language feature pushes me to change the abstract class to be an
>             interface *just to get the new static method behaviour*. In
>             essence I
>             have to make a new trade off between the right tool for the job
>             (abstract class) and the right tool to avoid static method bugs
>             (interface).
>
>             It occured to me that as this was a new dliemma, I should
>             report it
>             here on lambda-dev. And propose a possible solution.
>
>             Consider a new annotation @NotInherited that is only
>             applicable to
>             static methods. If a developer places it on a static method,
>             then the
>             method cannot be invoked by subclasses:
>
>             public class A {
>                 @NotInherited
>                 public static void foo() {..}
>             }
>             public class B extends A {
>             }
>             {  // other code
>                 A.foo();  // compiles
>                 B.foo();  // would not compile with this proposal
>             }
>
>             - Many IDEs support something similar today, but this would be
>             enforced at the compiler level.
>             - It is similar to @Override in conceptual scope, and is
>             therefore
>             suitable for an annotation.
>             - It would not change the compiled bytecode at all, other
>             than the
>             standard storage for the additional annotation.
>             - There are no reflection, security or backwards
>             compatibility issues
>             that I can see.
>             - Adding the annotation to a previously published API would be
>             backwards incompatible at the source level, but not the
>             binary level
>             - When compiling B against a previously compiled A, the
>             annotation
>             would be read from A's bytecode.
>             - The annotation would not be processed by the JVM or
>             verifier, thus
>             B.foo() would be valid if it could be compiled (such as in a
>             separate
>             compilation scenario).
>             - The change appears to be small, and thus not require a
>             large effort
>             to implement
>
>             The annotation could be added to the JDK without enforcing it in
>             javac, but that would seem to be a change not worth doing as
>             it would
>             rely on IDEs.
>
>             Its easy to say that this is an old problem and so nothing
>             needs to be
>             done. But I hope I've tried to indicate that I think
>             lambda's static
>             methods on interfaces has changed the nature of the old
>             problem and
>             made it potentially more problematic in code design terms.
>
>             Thoughts?
>             Stephen
>
>
>
>


More information about the lambda-dev mailing list