静态方法的私有构造函数

时间:2013-06-04 14:17:28

标签: java

我创建了以下类来使用常量验证某些值。为什么我收到以下错误?由于不需要启动类来使用静态方法,但仍然为什么要尝试启动。我正在使用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

2 个答案:

答案 0 :(得分: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。

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

答案 1 :(得分:-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);
};