Enum字段中的ArrayList元素为空。这样做的正确方法是什么?

时间:2016-05-18 03:30:44

标签: java android arraylist enums

我的理论是初始化时的第一个枚举被强制首先初始化第二个枚举以构建第一个ArrayList,但是当它构建第二个枚举的ArrayList时,它不会卡在逻辑循环中,而是设置值为Null。

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        for (Ingredients ingredient: Ingredients.values()){
            Log.d("debug", ingredient.recipes.toString());
        }

        for (Recipes recipe: Recipes.values()){
            Log.d("debug",recipe.ingredients.toString());
        }
    }

    enum Ingredients {
        APPLE(new ArrayList<>(Arrays.asList(Recipes.APPLE_FRITTER))),
        BANANA(new ArrayList<>(Arrays.asList(Recipes.BANANA_FRITTER))),
        FLOUR(new ArrayList<>(Arrays.asList(Recipes.APPLE_FRITTER, Recipes.BANANA_FRITTER))),
        SUGAR(new ArrayList<>(Arrays.asList(Recipes.APPLE_FRITTER, Recipes.BANANA_FRITTER)));

        final ArrayList<Recipes> recipes;

        Ingredients(ArrayList<Recipes> products) {
            this.recipes = products;
        }
    }

    enum Recipes {
        APPLE_FRITTER(new ArrayList<>(Arrays.asList(Ingredients.APPLE, Ingredients.FLOUR, Ingredients.SUGAR))),
        BANANA_FRITTER(new ArrayList<>(Arrays.asList(Ingredients.BANANA, Ingredients.FLOUR, Ingredients.SUGAR)));

        final ArrayList<Ingredients> ingredients;

        Recipes(ArrayList<Ingredients> ingredients) {
            this.ingredients = ingredients;
        }
    }
}

这是logcat:

D/debug: [APPLE_FRITTER]
D/debug: [BANANA_FRITTER]
D/debug: [APPLE_FRITTER, BANANA_FRITTER]
D/debug: [APPLE_FRITTER, BANANA_FRITTER]
D/debug: [null, null, null]
D/debug: [null, null, null]

这段代码很遗憾只是一个较大项目的一个小例子,它依赖于这项工作,如果我需要有效地废弃所有东西并重新开始,只需要一些确认。

当然,这里有一些技巧我想念,那太棒了。非常感谢您的见解。

编辑:在发布此消息后不久,我认为在回应承认失败时,我想出了我认为是一个能够解决问题的精彩重构。它没有工作,但产生了不同的错误。分享有兴趣的人:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        for (Ingredients ingredient: Ingredients.values()){
            Log.d("debug", ingredient.recipes.toString());
        }

        for (Recipes recipe: Recipes.values()){
            Log.d("debug",recipe.ingredients.toString());
        }
    }

    private final static ArrayList<Recipes> appleRecipes = new ArrayList<>(Arrays.asList(Recipes.APPLE_FRITTER));
    private final static ArrayList<Recipes> bananaRecipes = new ArrayList<>(Arrays.asList(Recipes.BANANA_FRITTER));
    private final static ArrayList<Recipes> flourRecipes = new ArrayList<>(Arrays.asList(Recipes.APPLE_FRITTER, Recipes.BANANA_FRITTER));
    private final static ArrayList<Recipes> sugarRecipes = new ArrayList<>(Arrays.asList(Recipes.APPLE_FRITTER, Recipes.BANANA_FRITTER));

    private final static ArrayList<Ingredients> appleFritterIngredients = new ArrayList<>(Arrays.asList(Ingredients.APPLE, Ingredients.FLOUR, Ingredients.SUGAR));
    private final static ArrayList<Ingredients> bananaFritterIngredients = new ArrayList<>(Arrays.asList(Ingredients.BANANA, Ingredients.FLOUR, Ingredients.SUGAR));

    enum Ingredients {
        APPLE(appleRecipes),
        BANANA(bananaRecipes),
        FLOUR(flourRecipes),
        SUGAR(sugarRecipes);

        final ArrayList<Recipes> recipes;

        Ingredients(ArrayList<Recipes> products) {
            this.recipes = products;
        }
    }

    enum Recipes {
        APPLE_FRITTER(appleFritterIngredients),
        BANANA_FRITTER(bananaFritterIngredients);

        final ArrayList<Ingredients> ingredients;

        Recipes(ArrayList<Ingredients> ingredients) {
            this.ingredients = ingredients;
        }
    }
}

相关logcat:

D/debug: [APPLE_FRITTER]
D/debug: [BANANA_FRITTER]
D/debug: [APPLE_FRITTER, BANANA_FRITTER]
D/debug: [APPLE_FRITTER, BANANA_FRITTER]
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.util.ArrayList.toString()' on a null object reference

1 个答案:

答案 0 :(得分:0)

问题是你有两个枚举在它们的构造函数中相互引用,这是一个循环引用。 您可以使用setter初始化来解决此问题。

免费提示: Arrays.asList 返回 new ArrayList ,因此您无需再次将其包装在 new ArrayList 。 =)

enum Ingredients {
    APPLE,
    BANANA,
    FLOUR,
    SUGAR;

    static{
        APPLE.setRecipes(Arrays.asList(Recipes.APPLE_FRITTER));
        BANANA.setRecipes(Arrays.asList(Recipes.BANANA_FRITTER));
        FLOUR.setRecipes(Arrays.asList(Recipes.APPLE_FRITTER, Recipes.BANANA_FRITTER));
        SUGAR.setRecipes(Arrays.asList(Recipes.APPLE_FRITTER, Recipes.BANANA_FRITTER));
    }

    List<Recipes> recipes;

    private void setRecipes(List<Recipes> products){
        this.recipes = products;
    }

}

enum Recipes {
    APPLE_FRITTER,
    BANANA_FRITTER;

    static{
        APPLE_FRITTER.setIngredients(Arrays.asList(Ingredients.APPLE, Ingredients.FLOUR, Ingredients.SUGAR));
        BANANA_FRITTER.setIngredients(Arrays.asList(Ingredients.BANANA, Ingredients.FLOUR, Ingredients.SUGAR));
    }

    List<Ingredients> ingredients;

    private void setIngredients(List<Ingredients> ingredients) {
        this.ingredients = ingredients;
    }

}

Java Classloader是JRE的一部分,它将Java类动态加载到JVM中。通常只按需加载类。

当JVM开始加载成分时。它会在 Ingredients.APPLE 的构造函数中看到 Recipes.APPLE_FRITTER ,因此它开始加载食谱。它在 Recipes.APPLE_FRITTER &#39;中看到 Ingredients.APPLE Ingredients.FLOUR Ingredients.SUGAR 引用的构造函数,但我们仍然在 Ingredients.APPLE 的构造函数中,所以 Ingredients.APPLE Ingredients.FLOUR Ingredients.SUGAR 此时为空,因此 Recipes.APPLE_FRITTER 的构造函数将所有项目都设为null。

抱歉英文不好。 :)