如何在实例化Question类时保留ArrayList选项,避免被修改?
解决复用ArrayList导致Question选项被修改的问题
问题本质
Java里ArrayList是引用类型,你所有的Question对象都接收了同一个ArrayList实例的引用。也就是说,不管创建多少个Question,它们的choices字段指向的都是内存里同一个列表。后续清空、修改这个列表时,所有已创建的Question的选项都会跟着变化。
两种解决办法
方法1:每次创建Question时,使用新的ArrayList实例
不用复用同一个c,每次准备新选项前直接新建一个ArrayList,这样每个Question拿到的都是独立的列表,互相不影响。
修改后的代码如下:
public static ArrayList<Question> allInitialQuestions(ArrayList<Question> q) { // 第一个问题的选项,新建列表 ArrayList<String> c = new ArrayList<String>(); c.add("Pacific"); c.add("Atlantic"); c.add("Arctic"); c.add("Indian"); q.add(new Question("Geography","Which ocean is the largest?", c, "Pacific", "The Pacific Ocean stretches to an astonishing 63.8 million square miles!")); // 第二个问题,新建列表 c = new ArrayList<String>(); c.add("192"); c.add("195"); c.add("193"); c.add("197"); q.add(new Question("Geography", "How many countries are in the world?", c, "195", "Africa has the most countries of any continent with 54.")); // 第三个问题,新建列表 c = new ArrayList<String>(); c.add("Mississippi"); c.add("Nile"); c.add("Congo"); c.add("Amazon"); q.add(new Question("Geography", "What is the name of the longest river in the world?", c, "Nile","Explorer John Hanning Speke discovered the source of the Nile on August 3rd, 1858.")); // 第四个问题,新建列表 c = new ArrayList<String>(); c.add("United States"); c.add("China"); c.add("Japan"); c.add("India"); q.add(new Question("Geography","Which country has the largest population?" ,c, "China", "Shanghai is the most populated city in China with a population of 24,870,895.")); // 第五个问题,新建列表 c = new ArrayList<String>(); c.add("Mars"); c.add("Mercury"); c.add("Venus"); c.add("Jupiter"); q.add(new Question("Geography","Which planet is closest to Earth?",c,"Venus","Even though Venus is the closest, the planet it still ~38 million miles from Earth!")); // 第六个问题,新建列表 c = new ArrayList<String>(); c.add("Sega"); c.add("Nintendo"); c.add("Sony"); c.add("Atari"); q.add(new Question("Video Games", "Which company created the famous plumber Mario?", c, "Nintendo", "Nintendo created Mario in 1981 for the arcade game Donkey Kong.")); // 第七个问题,新建列表 c = new ArrayList<String>(); c.add("Sonic"); c.add("Tales"); c.add("Knuckles"); c.add("Amy"); q.add(new Question("Video Games", "What is the name of the famous video character who is a blue hedgehog?",c,"Sonic", "In some official concept art, Sonic was originally meant to be a rabbit.")); // 第八个问题,新建列表 c = new ArrayList<String>(); c.add("Wii Sports"); c.add("Grand Theft Auto V"); c.add("Tetris"); c.add("Minecraft"); q.add(new Question("Video Games","As of 2022, which of the following is the best selling video game of all time?",c,"Minecraft","As of 2022, Minecraft has sold over 238 million units.")); return q; }
方法2:修改Question类的构造方法,内部复制传入的列表
如果不想每次新建列表,可以在Question的构造方法里,把传入的ArrayList复制一份,这样Question内部保存的是自己的副本,外部修改原列表不会影响它。
修改Question的构造方法示例:
public class Question { private String genre; private String question; private ArrayList<String> choices; private String answer; private String funFact; public Question(String genre, String question, ArrayList<String> choices, String answer, String funFact) { this.genre = genre; this.question = question; // 复制传入的列表,创建独立副本 this.choices = new ArrayList<>(choices); this.answer = answer; this.funFact = funFact; } // 其他方法... }
这样你的原代码不用改动,直接复用c也没问题,因为每个Question都会自己复制一份选项列表。
内容的提问来源于stack exchange,提问作者EMAN-GAMING
相关产品推荐
相关产品推荐

