空点异常|枚举构造函数中的“this”导致 NPE

public class Test {
    public static void main(String[] args) {
        Platform1 p1=Platform1.FACEBOOK; //giving NullPointerException.
        Platform2 p2=Platform2.FACEBOOK; //NO NPE why?
    }
}

enum Platform1{
    FACEBOOK,YOUTUBE,INSTAGRAM;
    Platform1(){
        initialize(this);
    };
    public void initialize(Platform1 platform){
        switch (platform) {
        //platform is not constructed yet,so getting `NPE`.
        //ie. we doing something like -> switch (null) causing NPE.Fine!
        case FACEBOOK:
            System.out.println("THIS IS FACEBOOK");
            break;
        default:
            break;
        }
    }
}

enum Platform2{
    FACEBOOK("fb"),YOUTUBE("yt"),INSTAGRAM("ig");
    private String displayName;
    Platform2(String displayName){
        this.displayName=displayName;
        initialize(this);
    };  
    public void initialize(Platform2 platform){
        switch (platform.displayName) {
        //platform not constructed,even No `NPE` & able to access its properties.
        //switch (null.displayName) -> No Exception Why?
        case "fb":
            System.out.println("THIS IS FACEBOOK");
            break;
        default:
            break;
        }
    }
}

谁能解释一下为什么有在里面,但不在.在第二种情况下,我们如何能够在构造对象之前访问枚举对象及其属性?NullPointerExceptionPlatform1Platform2


答案 1

完全。正如@PeterS在正确构造枚举之前使用枚举所提到的一样,它会导致 NPE,因为 values() 方法在未构造的枚举上被调用。

还有一点,我想在这里补充一点,两者都试图在switch()中使用未构造的枚举,但NPE只在.这背后的原因如下:-Platform1Platform2Platform1

 public void initialize(Platform1 platform){
        switch (platform) {

来自枚举的上述代码片段在交换机中使用枚举对象,其中使用内部数组并使用此数组方法来初始化,因此您将获得NPE。但是在 中,比较已经初始化并且发生字符串比较,因此没有 NPE。Platform1platform$SwitchMap$Platform1[]values()Platform2switch (platform.displayName)displayName

以下是反编译代码的片段:-

平台1

 static final int $SwitchMap$Platform1[] =
            new int[Platform1.values().length];

平台2

switch ((str = platform.displayName).hashCode())
    {
    case 3260: 
      if (str.equals("fb")) {

答案 2

你不能这样做,因为你试图在枚举被正确构建之前处理它。(如在构建的完整内容中一样)。您会注意到该错误试图引用枚举的值部分:

Caused by: java.lang.NullPointerException
    at Platform1.values

在处理对象之前,您需要允许对象在内部正确初始化。这将工作:

public static void main(String[] args) {
    Platform1 p1=Platform1.FACEBOOK;
    p1.initialize(p1);
    //Platform1.YOUTUBE giving NullPointerException why?
    Platform2 p2=Platform2.FACEBOOK;
    //NO NPE
}

enum Platform1{
    FACEBOOK,YOUTUBE,INSTAGRAM;
    Platform1(){
        //initialize(this);
    };

显然,您的初始化函数应该重命名,因为它只是报告值。第二个示例提供了值,因此可以正常工作。

来自其中一个 Java 文档:

枚举声明定义一个类(称为枚举类型)。枚举类主体可以包含方法和其他字段。编译器在创建枚举时会自动添加一些特殊方法。例如,它们具有一个静态值方法,该方法返回一个数组,其中包含枚举的所有值(按声明顺序排列)。此方法通常与 for-each 构造结合使用,以循环访问枚举类型的值。例如,下面 Planet 类示例中的此代码将循环访问太阳系中的所有行星。