68

Since an enum constructor can only be invoked by its constants, why is it then allowed to be package-private?

fireshadow52
  • 6,298
  • 2
  • 30
  • 46
Tobias
  • 1,062
  • 1
  • 9
  • 15
  • 9
    to allow to save a bit on code space and to avoid needless verbosity (like interfaces don't need `public abstract` before every method) – ratchet freak Oct 13 '11 at 00:22
  • @ratchetfreak: It's not like interfaces. Interface methods are *always* `public abstract`. Making the modifiers explicit is allowed, but there's no way to change them. – Ryan Stewart Oct 13 '11 at 00:28
  • @RyanStewart there's also no way to call a enum constructor yourself so it becomes logically private and allowing package private allows saving those few chars – ratchet freak Oct 13 '11 at 00:43
  • 6
    I stand corrected: "If no access modifier is specified for the constructor of an enum type, the constructor is private." -- [JLS 8.8.3](http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.8.3). It seems the java tutorial is incorrect or at least misleading. – Ryan Stewart Oct 13 '11 at 01:14

2 Answers2

105

The constructor actually isn't package-private... it's implicitly private the way interface methods are implicitly public even if you don't add the keyword.

The relevant section of the JLS (§8.8.3) states:

If no access modifier is specified for the constructor of a normal class, the constructor has default access.

If no access modifier is specified for the constructor of an enum type, the constructor is private.

It is a compile-time error if the constructor of an enum type (§8.9) is declared public or protected.

Pang
  • 9,564
  • 146
  • 81
  • 122
ColinD
  • 108,630
  • 30
  • 201
  • 202
5

It's a quirk of the language: enum constructors are implicitly private.

Interestingly, if you declare a package-visible enum constructor, like this:

public enum MyEnum {
    A(0),
    B(1);

    private final int i;

    MyEnum(int i) {
        this.i = i;
    }

    public int getI() {
        return i;
    }
}

you can't refer to it from another class in the package. If you try, you get the compiler error:

Cannot instantiate the type MyEnum

Bohemian
  • 412,405
  • 93
  • 575
  • 722
  • Apparently you can try this with enum being static nested class or in a method of the enum. Yes, compilation fails with said error. – Vlasec Apr 11 '16 at 08:05
  • 2
    "if you declare a package-visible enum constructor"...but actually there is no way to do that. – raghavsood33 Jul 11 '17 at 05:51
  • @raghavsood33 yes you can. See the compilable code I added to my answer that demonstrates a package-visible constructor. – Bohemian Jul 11 '17 at 12:41
  • 1
    The constructor in your code is not package-private; it is private. It just lacks an explicit `private` keyword. That would only make it package-private if it were a class, but it is an enum, not a class. – kaya3 Feb 14 '20 at 14:49