Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enum implementing interface, interface and method visibility

I just came accross the following code, which surprised me a little bit, I converted it to a simple SSCEE here though:

custompackage.package1.MyEnum.java

public enum MyEnum implements MyInterface {
    CONSTANT_ONE() {
        @Override
        public void myMethod() {
            //do something very interesting
        }
    },
    CONSTANT_TWO() {
        @Override
        public void myMethod() {
            //do something very interesting
        }
    };
}

interface MyInterface {
    void myMethod();
}

Now from outside this package, I can do the following:

Consumer<MyEnum> myMethod = MyEnum::myMethod;

However I am not able to use MyInterface at all, which I understand as it is package-private to custompackage.package1.

I don't understand what exactly is going on though, it seems like MyEnum got the myMethod() method added, but it does not implement (from the outside) MyInterface.
How does this work?

like image 805
skiwi Avatar asked May 22 '14 15:05

skiwi


3 Answers

Well you can't see MyInterface from outside the package, as you said - but MyEnum effectively has a public abstract myMethod() method, which you're able to use as a method reference.

Leaving aside fancy new Java 8 features, this is valid (even outside the package):

// Even MyEnum x = null; will compile, but obviously fail
MyEnum x = MyEnum.CONSTANT_ONE;
x.myMethod();

The method is inherited from the interface, even though the interface itself is not visible.

This isn't specific to interfaces and enums, either. For example:

// Foo.java
package foo;

class SuperFoo {
   public void publicMethod() {
   }
}

public class Foo extends SuperFoo {
}

// Bar.java
package bar;

import foo.Foo;

public class Bar {
    public void test() {
        Foo foo = new Foo();
        foo.publicMethod();
    }
}

This compiles fine, even though Foo doesn't even override publicMethod. As far as Bar is concerned, it's inherited from somewhere, but it doesn't know where!

like image 196
Jon Skeet Avatar answered Oct 23 '22 10:10

Jon Skeet


In interfaces methods are public abstract by default. fields are public static final

the reason you can use the method is that the interface is package local. Try making it public.

like image 1
Peter Lawrey Avatar answered Oct 23 '22 10:10

Peter Lawrey


However I am not able to use MyInterface at all, which I understand as it is package-private to custompackage.package1.

The interface is package-private, but all methods (and fields) are (implicitly or explicit) public.

it seems like MyEnum got the myMethod() method added, but it does not implement (from the outside) MyInterface.

MyEnum has a public method called myMethod(), regardless of whether it inherited the (public) abstract method from the interface or whether it declared the method itself. Said another way, even if the outside cannot see the interface, the outside can certainly see MyEnum and see MyEnum.myMethod().

like image 1
Bert F Avatar answered Oct 23 '22 11:10

Bert F