【问题标题】:How to call additional method in enums?如何在枚举中调用附加方法?
【发布时间】:2011-05-11 06:07:14
【问题描述】:
enum Enum1
{
    BIG(8), HUGE(10)
    {
        public String getName()
        {
            return "Huge";
        }

        public String getContry()
        {
            return "India";
        }//additional Method
    },
    OVERWHELMING(16)
    {
        public String getName()
        {
            return "OVERWHELMING";
        }
    };
    private int ounces;

    public int getOunes()
    {
        return ounces;
    }

    public String getName()
    {
        return "Ponds";
    }

    Enum1(int ounces1)
    {
        ounces = ounces1;
    }
}

class EnumAsInnerClass
{
    Enum1 enumInnerClass;

    public static void main(String[] args)
    {
        EnumAsInnerClass big = new EnumAsInnerClass();
        big.enumInnerClass = Enum1.BIG;
        EnumAsInnerClass over = new EnumAsInnerClass();
        over.enumInnerClass = Enum1.OVERWHELMING;
        EnumAsInnerClass huge = new EnumAsInnerClass();
        huge.enumInnerClass = Enum1.HUGE;
        System.out.println(big.enumInnerClass.getName());//Ponds        
        System.out.println(over.enumInnerClass.getName());//OVERWHELMING
        System.out.println(huge.enumInnerClass.getName());//Huge
    }
}

考虑上面的例子。如何调用方法 getCountry for HUGE?

如果没有办法调用这个方法,为什么Java会认为它是合法的?

【问题讨论】:

  • 由于enum 的整个想法是基于它的所有值都以统一的方式起作用的事实,我认为仅在单个值上实现方法不是一个好主意(或在值的子集上,通常)。为什么要这样做?

标签: java enums


【解决方案1】:

这一点也不奇怪。

当您定义enum 类型(在您的情况下为Enum1)并为其声明值时,它们的引用类型将是定义的类型(Enum1)。当您在 enum 声明中定义方法时,您刚刚创建了匿名子类

public enum Enum1 {

    OVERWHELMING(16) {

        public String getName() {
            return "OVERWHELMING";
        }
    };

    // And the remaining constructors, fields and methods
}

而且您不能通常从定义本身之外调用匿名类的方法。同样,someOtherMethod() 也无法从外部访问:

ActionListener al = new ActionListener() {

    @Override
    public void actionPerformed(ActionEvent e) {
        someOtherMethod();
    }

    public void someOtherMethod() {
        System.out.println("Some other method!");
    }
};

但是,可以从声明本身访问这些方法,例如 stated in this answer

注意:就像Joachim Sauerhis comment 中所说,这可能不是最好的设计。例如,您应该将方法移动到 Enum1 类型。


还有办法。可以通过反射访问方法:

Class<?> clazz = Enum1.HUGE.getClass();
Method method = clazz.getMethod("getCountry");
System.out.println(method.invoke(Enum1.HUGE)); // Prints "India"

【讨论】:

    【解决方案2】:

    如果没有办法调用这个方法那为什么java会认为是合法的呢?

    您仍然可以在枚举值定义中调用它。比如改getName()函数:

    // ...
    HUGE(10)
    {
        public String getName()
        {
            // Call additional Method
            return "Huge" + getCountry();
        }
    
        public String getContry()
        {
            return "India";
        } // additional Method
    },
    // ...
    

    否则,您需要被它覆盖才能调用它。

    【讨论】:

      【解决方案3】:

      (正如将近 4 年后所指出的,我最初的答案是不正确的。)

      你甚至不能用特定的枚举调用Enum1.HUGE.getCountry(),这有点令人惊讶......但即使你可以,你也不能用任意的Enum1 值这样做,这会更普遍有用。

      解决方案是阻止它成为附加方法 - 将 getCountry() 方法添加到 Enum1 中,要么返回默认值,要么可能引发异常。然后HUGE 可以覆盖该方法。

      如果你可以声明一个特定的枚举值实现了一个接口,那就太好了,但似乎没有语法。

      【讨论】:

      • 感谢您的快速回答,但这是不可能的,因为它仅被声明为 HUGE
      • @ponds 这就是为什么你不能在Enum1 变量上调用getCountry(),因为你不知道你是有一个HUGE 还是只有一个BIG。除此之外,是否有充分的理由仅在 HUGE 中使用该方法?你为什么不像乔恩建议的那样在Enum1 中声明它?
      • 刚刚遇到这个问题,这是不正确的 - 您不能在 Enum1 的声明之外调用 HUGE.getCountry - 请参阅 JLS 第 8.9.1 节
      【解决方案4】:

      enum 是一个类型定义,类似于一个类,所以Enum1 的接口中没有getCountry() 方法。

      编辑:替代解决方案

      可以做的是在Enum1 中定义所需的方法,并在各个枚举值中覆盖它们。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-08-30
        • 1970-01-01
        • 1970-01-01
        • 2021-04-16
        • 1970-01-01
        • 2019-04-18
        相关资源
        最近更新 更多