简体   繁体   English

枚举字段为Null时ArrayList的元素。 正确的方法是什么?

[英]Elements of ArrayList in Enum field Null. What is the correct way to do this?

My theory here is that the first enum upon initialization is forced to initialize the second enum first to build the first ArrayList, but when it builds the ArrayList of the second enum, rather than getting stuck in a logical loop, it sets the values to Null. 我的理论是,在初始化时首先强制第一个枚举初始化第二个枚举以构建第一个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;
        }
    }
}

Here is the logcat: 这是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]

This code is sadly just a small example of a much larger project that depends on this working and if I need to effectively scrap everything and start over, just need some confirmation. 不幸的是,这段代码只是一个较大项目的一个小示例,该项目取决于此工作,如果我需要有效地废弃所有内容并重新开始,则只需要进行一些确认即可。

Of course of there is some trick here I am missing, that would be awesome. 当然,这里缺少一些技巧,那太棒了。 Thank you either way for your insight. 无论哪种方式,谢谢您的见解。

edit: Shortly after posting this, I think in response to admitting to defeat, I came up with what I thought was a brilliant refactor that would solve the issue. 编辑:发布此消息后不久,我想回应认输,我想出了一个我认为是可以解决该问题的出色重构。 It didn't work but produced a different error. 它不起作用,但是产生了另一个错误。 Sharing for those interested: 分享给有兴趣的人:

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;
        }
    }
}

And relevent logcat: 和relevent 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

The problem is that you have two enums referencing each other in their constructors , this is a circular reference. 问题是您有两个枚举在其构造函数中相互引用 ,这是一个循环引用。 You can solve this with setter initialization. 您可以使用setter初始化来解决此问题。

Free tip: Arrays.asList returns a new ArrayList , so you don't need to wrap it again in a new ArrayList . 免费提示: Arrays.asList返回新的ArrayList ,因此您无需再次将其包装在新的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;
    }

}

The Java Classloader is a part of the JRE that dynamically loads Java classes into the JVM. Java Classloader是JRE的一部分,该JRE将Java类动态地加载到JVM中。 Usually classes are only loaded on demand. 通常,仅按需加载类。

When the JVM starts classloading Ingredients . JVM何时开始类加载Ingredients It sees the Recipes.APPLE_FRITTER in Ingredients.APPLE 's constructor, so it starts classloading Recipes . 它在Ingredients.APPLE的构造函数中看到Recipes.APPLE_FRITTER ,因此开始类加载Recipes It sees Ingredients.APPLE , Ingredients.FLOUR and Ingredients.SUGAR references in Recipes.APPLE_FRITTER 's constructor, but we are still in Ingredients.APPLE 's constructor, so Ingredients.APPLE , Ingredients.FLOUR and Ingredients.SUGAR are null at this point, so Recipes.APPLE_FRITTER 's constructor gets all items as null. 它在Recipes.APPLE_FRITTER的构造函数中看到Ingredients.APPLEIngredients.FLOURIngredients.SUGAR引用,但我们仍在Ingredients.APPLE的构造函数中,因此Ingredients.APPLEIngredients.FLOURIngredients.SUGAR此处为null点,因此Recipes.APPLE_FRITTER的构造函数将所有项目获取为null。

Sorry for the bad english. 对不起,英语不好。 :) :)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM