什么时候抛出java.lang.EnumConstantNotPresentException?

时间:2015-07-07 07:07:13

标签: java enums runtimeexception

根据java API,当应用程序尝试按名称访问枚举常量并且枚举类型不包含具有指定名称的常量时,将抛出EnumConstantNotPresentException。

因此我决定提出一个抛出java.lang.EnumConstantNotPresentException的场景,所以我写了三个类。

MyEnum课程:

package my.enumtest;

enum MyEnum {
    A, B, C;
}

MyEnumTest1类:

package my.enumtest;

    import my.enumtest.MyEnum;

    class MyEnumTest1 {

        public static void main(String [] args) {
            System.out.println(MyEnum.A);        
        }        
    }

MyEnumTest2类:

package my.enumtest;

import my.enumtest.MyEnum;

class MyEnumTest2 {

    public static void main(String [] args) {
        System.out.println(MyEnum.valueOf("A"));        
    }
}

我编译了所有三个,然后我更改了MyEnum类以删除常量'A'并重新编译它:

package my.enumtest;

enum MyEnum {
    B, C;
}

在使用新的MyEnum类执行MyEnumTest1时,我遇到以下异常:

  

线程“main”中的异常   java.lang.NoSuchFieldError:A           at my.enumtest.MyEnumTest1.main(MyEnumTest1.java:8)

在使用新的MyEnum类执行MyEnumTest2时,我遇到以下异常:

  

线程“main”中的异常java.lang.IllegalArgumentException:无枚举   不断的my.enumtest.MyEnum.A           在java.lang.Enum.valueOf(未知来源)           at my.enumtest.MyEnum.valueOf(MyEnum.java:3)           at my.enumtest.MyEnumTest2.main(MyEnumTest2.java:8)

正如你所看到的,我没有得到EnumConstantNotPresentException,所以有人可以提供我使用EnumConstantNotPresentException类吗?

P.S。我知道用于反复阅读注释的API可以抛出此异常,但我正在寻找更明显(更简单)的场景。

2 个答案:

答案 0 :(得分:3)

如果你想知道什么时候抛出特定异常,你应该做的第一件事就是按照JB Nizet提到的那样阅读the documentation。它说:

  

当应用程序尝试按名称访问枚举常量并且枚举类型不包含具有指定名称的常量时抛出。 API used to read annotations reflectively可以抛出此异常。

该链接跟随AnnotationElement文档说明:

  

类似地,如果注释中的枚举常量不再出现在枚举类型中,则尝试读取枚举值成员将导致EnumConstantNotPresentException

这足以制作一个例子。 创建以下类:

// TestEnum.java
public enum TestEnum {
    A, B, C;
}

// TestAnnotation.java
import java.lang.annotation.*;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation {
    TestEnum value();
}

// TestClass.java
@TestAnnotation(TestEnum.C)
public class TestClass {

}

// ReadAnnotation.java
public class ReadAnnotation {
    public static void main(String[] args) {
        System.out.println(TestClass.class.getAnnotation(TestAnnotation.class).value());
    }
}

编译所有内容并运行ReadAnnotation。你会得到C

现在从C中删除TestEnum并仅重新编译TestEnum类,保留其他类。如果您现在启动ReadAnnotation,您将获得:

Exception in thread "main" java.lang.EnumConstantNotPresentException: TestEnum.C
    at sun.reflect.annotation.EnumConstantNotPresentExceptionProxy.generateException(Unknown Source)
    at sun.reflect.annotation.AnnotationInvocationHandler.invoke(Unknown Source)
    at com.sun.proxy.$Proxy1.value(Unknown Source)
    at ReadAnnotation.main(ReadAnnotation.java:4)

如果您想知道它是否可以被其他任何东西抛出,您可以扫描JDK源以获取此异常名称。我没有发现任何其他提及这个例外,所以似乎反射是唯一可能的情况。

答案 1 :(得分:0)

java中的枚举通常也称为合成糖具有什么意义?

枚举常量将转换为公共静态最终MyEnum字段,其中包含枚举常量的名称以及编译时类的构造函数的值。 这意味着通过访问MyEnum.MY_CONSTANT,您可以访问字段

public static final MyEnum MY_CONSTANT = new MyEnum();

由于反射API现在还提供了通过getEnumConstants()isEnumConstant()检查枚举常量的方法(参见指南中的Enamiming Enums),java有一种方法可以判断哪个字段是枚举常量,哪个字段是场不是。所以这些领域并不像你在第一段后想到的那么简单。

抛出NoSuchFieldException,因为......很好,相应的枚举没有创建这样的字段。

反射API抛出IllegalArgumentException,因为它是为该API设计的异常,例如Enum#valueOf()。该方法使用反射按名称(字符串)查找给定的枚举常量。