【问题标题】:Private enum constructor私有枚举构造函数
【发布时间】:2011-10-30 02:42:39
【问题描述】:

enum 的构造函数是私有的。那是什么意思?

public enum SLocale {

    EN_US(Locale.US, "www.abc.com", "www.edc.com", "www.vvv.com",
            "www.earn.com");

    List<String> domains;
    Locale loc;
    IMap map;

    private SLocale(Locale loc, String... domains) {
        this.domains = Arrays.asList(domains);
        this.loc = loc;
        this.siteMap = Factory.getMap(loc);
    }

    public List<String> getDomains() {
        return domains;
    }

    public Locale getLoc() {
        return loc;
    }

    public ISiteMap getMap() {
        return map;
    }
}

【问题讨论】:

    标签: java enums


    【解决方案1】:

    私有构造函数只允许从类定义中构造对象。作为一个枚举,很容易混淆,所以我通常发现将枚举视为具有一些特殊功能的类更容易。所以当你写的时候:

    SLocale.EN_US
    

    基本上是参数

    Locale.US, "www.abc.com", "www.edc.com", "www.vvv.com", "www.earn.com"
    

    将被传递给私有构造函数,以便可以实例化枚举。枚举构造函数必须是私有的。

    【讨论】:

    • 哇,我见过的对 Enum 的最简单、最简单的解释。我终于明白了。
    • "当你编写时......参数......将被传递给构造函数"。请注意,我们在编写 SLocale.EN_US 时不会将参数传递给构造函数,因为所有枚举常量都是静态的,也就是说,即使我们不编写 SLocale.EN_US,在类加载时仍然会调用构造函数。
    【解决方案2】:

    发件人:http://download.oracle.com/javase/tutorial/java/javaOO/enum.html

    注意:枚举类型的构造函数必须是包私有或 私人访问。它会自动创建常量 在枚举主体的开头定义。您不能调用枚举 自己构造函数。

    你实际上不能有一个公共枚举构造函数。

    【讨论】:

    • 如果您不使用“private”,那么编译器会为您添加它。您可以在有和没有“私有”的情况下编译代码,并对两个类文件进行“差异”;它们是相同的。您还可以在枚举类上执行“javap -p -c”来比较...构造函数始终是私有的。
    • 规范中也写到:“在枚举声明中,没有访问修饰符的构造函数声明是私有的。”(见jls-8.9.2
    【解决方案3】:

    您需要此构造函数是私有的,因为枚举定义了一组有限的值(例如 EN_US、EN_UK、FR_FR、FR_BE)。如果构造函数是公共的,人们可能会创建更多的值(例如无效/未声明的值,例如 XX_KK 等)。这将扩展最初声明的值集。

    【讨论】:

      【解决方案4】:

      Enums 必须有专门的私有构造函数,这是因为 Enum 应该是唯一负责返回预定义实例的构造函数。

      【讨论】:

        【解决方案5】:

        在枚举的情况下,这与将其包私有的含义相同。实例化枚举的唯一方法是在枚举类中声明它们。枚举不能有公共构造函数。

        【讨论】:

          【解决方案6】:

          这意味着除了枚举“类”本身之外没有任何代码能够显式构造一个枚举对象

          【讨论】:

            【解决方案7】:
            public enum Day {
            
                SUNDAY(), MONDAY, TUESDAY(2), WEDNESDAY, THURSDAY, FRIDAY, SATURDAY;
            
                int value;
            
                private Day(int value) {
                    System.out.println("arg cons");
                    this.value = value;
                }
            
                private Day() {
                    System.out.println("no arg cons");
                }
            
                public static void main(String args[]) {
            
                }
            
            }
            

            输出: no arg cons no arg cons arg cons no arg cons no arg cons no arg cons no arg cons

            想象一下枚举如下:

            SUNDAY() 等价于static final Day SUNDAY = new Day();

            MONDAY也等价于static final Day MONDAY = new Day(); // without paranthesis it calls the no-arg constructor/default no-arg constrctor if no other constructor

            TUESDAY(2) 等价于static final Day TUESDAY = new Day(2);

            由于枚举必须被视为一种特殊类型的类,它允许“静态”对象 创建。由于您不能在枚举类之外创建对象,所有对象的创建都发生在类声明级别本身,因此对象创建的“静态”在这里是有意义的。

            在 Enum 中,所有对象的创建(即静态最终常量创建,准确地说)必须在该枚举类本身(以及因此私有构造函数)内进行,因为 Enum 的目的是只有一组固定的与您的应用程序相关的有意义的常量,并消除无意义的语句/实例,例如 Day SOME_EIGHTH_DAY_THINKING_TO_BE_VALID = new Day(8)

            【讨论】:

              【解决方案8】:

              我会认为 Enums 是单例的,因此构造函数必须是私有的,如果它们不是单例的,那么想想会出现什么问题。当你声明一个构造函数时,你正在实现java的最终静态行为。你只能初始化一次。这种 impl 来自需要在应用程序启动时加载一次的属性文件或 cfg 文件。正常枚举和常量的问题是您必须更改 java 代码,并且需要重新编译。但是如果您是从文件加载,那么我们可以更改它并重新启动,更改将生效。希望我能对此有所了解。

              【讨论】:

              • 我认为,枚举常量必须在枚举类型中硬编码。我们无法从文件中加载它们。你能分享一些代码来证明你的陈述是正确的吗?
              猜你喜欢
              • 2016-07-17
              • 2011-12-06
              • 1970-01-01
              • 2012-11-18
              • 1970-01-01
              • 2011-08-20
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多