Archie
Archie

Reputation: 5421

Javac fails with "attempting to assign weaker access privileges" on intersection type

Consider this Java program:

public class IntersectionBug {

    public static interface FooInterface {
        public void foo();
    }

    public static class FooSupport {
        protected void foo() {
        }
    }

    public static class Whatever<T extends FooSupport & FooInterface> {
    }
}

It fails to compile under JDK 1.8 compiler:

$ javac IntersectionBug.java
IntersectionBug.java:12: error: foo() in FooSupport cannot implement foo() in FooInterface
    public static class Whatever<T extends FooSupport & FooInterface> {
                                 ^
  attempting to assign weaker access privileges; was public
1 error

Obviously, if some type T is both a FooSupport and a FooInterface, then it must have a public void foo(), so the error is bogus.

My question: is this a compiler bug, or does the JLS really specify that this program is invalid? If the latter is the case, why the sub-optimal JLS behavior here?

Upvotes: 1

Views: 452

Answers (1)

Stephan Herrmann
Stephan Herrmann

Reputation: 8178

JLS §4.9 defines intersection types and what are their members via the concept of a notional class. In your particular case the notional class is:

class <notional> extends FooSupport implements FooInterface {}

Please note the empty class body.

The JLS paragraph is meant to imply that the notional class must be well-formed, or a compile error occurs. Clearly a class that inherits a protected implementation for a public interface method is not well-formed.

I agree that there could be other ways of specifying an intersection type that would admit unknown subclasses of FooSupport that would resolve the above conflict by overriding the method with public visibility.

I believe the style of definition via the notional class was chosen to keep complexity at bay. See how succinct §4.9 is in comparison to other definitions.

PS: Also ecj rejects your example, saying:

The inherited method IntersectionBug.FooSupport.foo() cannot hide the public abstract method in IntersectionBug.FooInterface

Upvotes: 1

Related Questions