1

我创建了以下类来使用常量验证某些值。为什么我收到以下错误?由于类不需要被启动来使用静态方法,但仍然是它为什么要尝试启动。我正在使用 java 1.6 这是一个好习惯吗?

public final class Approver{

    // Avoids initiating this class
    private Approver() {
    }


    private static final List<String> APPROVED_LENGTH= new ArrayList<String>() {
        {
            addAll(KM_APPROVED_LIST);
            addAll(LM_APPROVED_LIST);
        }
    };

    private static final List<String> KM_APPROVED_LIST = new ArrayList<String>() {
        {
            add("L");
            add("G");
                    // so on
        }

    };
    private static final List<String> LM_APPROVED_LIST = new ArrayList<String>() {
        {
            add("P");
            add("K");
                    // so on
        }

    };
    public static boolean isApproved(String lenth) {
        return APRROVED_LENGTH.contains(length);
    }

从另一个班级

if(Approver.isApproved("K"))

{......}

错误

Caused by: java.lang.NoClassDefFoundError: Could not initialize class ...Approver.class
4

2 回答 2

6

如果您查看了错误的其余部分,我想您已经看到了问题所在。在本声明中:

private static final List<String> APPROVED_LENGTH= new ArrayList<String>() {
    {
        addAll(KM_APPROVED_LIST);
        addAll(LM_APPROVED_LIST);
    }
};

你正在使用KM_APPROVED_LISTLM_APPROVED_LIST而他们都是null......这意味着你正在调用addAll(null)它会抛出一个NullPointerException.

例如,这是我在一个简短的测试应用程序中看到的异常:

Exception in thread "main" java.lang.ExceptionInInitializerError
        at Test.main(Test.java:43)
Caused by: java.lang.NullPointerException
        at java.util.ArrayList.addAll(Unknown Source)
        at Approver$1.<init>(Test.java:14)
        at Approver.<clinit>(Test.java:12)
        ... 1 more

到那时,应该很清楚发生了什么。

初始化一个块中的所有内容会更干净static,IMO - 它消除了所有排序问题 - 以及避免讨厌的匿名类:

private static final List<String> APPROVED_LENGTH;
private static final List<String> KM_APPROVED_LIST;
private static final List<String> LM_APPROVED_LIST;

static {
    KM_APPROVED_LIST = new ArrayList<String>();
    KM_APPROVED_LIST.add("L");
    KM_APPROVED_LIST.add("G");
    LM_APPROVED_LIST = new ArrayList<String>();
    LM_APPROVED_LIST.add("P");
    LM_APPROVED_LIST.add("K");
    APPROVED_LENGTH = new ArrayList<String>();
    APPROVED_LENGTH.addAll(KM_APPROVED_LIST);
    APPROVED_LENGTH.addAll(LM_APPROVED_LIST);
}

或者,您可以重新排序字段并依赖静态变量初始化程序排序 - 但最好使用Guava使代码更清晰:

private static final List<String> KM_APPROVED_LIST =
    Lists.newArrayList("L", "G");
private static final List<String> LM_APPROVED_LIST =
    Lists.newArrayList("P", "K");
private static final List<String> APPROVED_LENGTH =
    Lists.newArrayList(Iterables.concat(KM_APPROVED_LIST, LM_APPROVED_LIST));

我应该指出,只需重新排序字段声明以便APPROVED_LENGTH最后声明即可解决问题 - 但它仍然不是很好的代码,IMO。

您可能还想考虑制作这些不可变列表。

于 2013-06-04T14:23:11.593 回答
-1

发生错误是因为您试图在静态上下文中创建匿名内部类:

private static final List<String> APPROVED_LENGTH= new ArrayList<String>() {
    {
        addAll(KM_APPROVED_LIST);
        addAll(LM_APPROVED_LIST);
    }
};

我很惊讶编译器允许这种情况发生,但我想它并没有做很多语义检查(即验证类可以被实例化)。无论如何,这里是如何修复它(以及一般初始化静态列表/映射的更好方法):

private static final List<String> APPROVED_LENGTH= new ArrayList<String>();
static {
    addAll(KM_APPROVED_LIST);
    addAll(LM_APPROVED_LIST);
};
于 2013-06-04T14:22:56.663 回答