Java中如何强制QAData类的数组固定为长度4?
如何在QAData类中强制数组长度为4?
嘿,这个问题问到点子上了——要保证QA数据的规范性,强制数组长度为4确实是很关键的需求。下面给你几个Java里实用的实现方案,按需选择就行:
1. 构造器内严格校验数组长度(最常用的方案)
在创建QAData对象的入口(构造器)里直接校验每个数组的长度,一旦不符合要求就抛出异常,从根源上拦截不合法的数据。同时为了避免外部修改内部数组,记得做防御性拷贝:
import java.util.Arrays; import java.util.Objects; public class QAData { private final String question; private final String[] options; private final boolean[] answerFlags; private final boolean[] selectedFlags; public QAData(String question, String[] options, boolean[] answerFlags, boolean[] selectedFlags) { this.question = Objects.requireNonNull(question, "问题文本不能为null"); // 校验每个数组的长度必须为4 validateArrayLength(options, "可选答案数组"); validateArrayLength(answerFlags, "正误标记数组"); validateArrayLength(selectedFlags, "用户选中标记数组"); // 拷贝数组,防止外部通过引用修改内部数据 this.options = Arrays.copyOf(options, 4); this.answerFlags = Arrays.copyOf(answerFlags, 4); this.selectedFlags = Arrays.copyOf(selectedFlags, 4); } // 针对Object数组的校验方法 private void validateArrayLength(Object[] array, String arrayName) { if (array == null || array.length != 4) { throw new IllegalArgumentException(arrayName + "必须是长度为4的数组"); } } // 重载boolean数组的校验方法 private void validateArrayLength(boolean[] array, String arrayName) { if (array == null || array.length != 4) { throw new IllegalArgumentException(arrayName + "必须是长度为4的数组"); } } // Getter方法也要返回拷贝,避免外部修改 public String[] getOptions() { return Arrays.copyOf(options, 4); } // 其他字段的getter同理实现... }
这样只要有人尝试用长度不是4的数组创建QAData,就会立刻抛出IllegalArgumentException,直接阻断不合法对象的生成。
2. 用不可变List替代数组(更安全直观)
数组本身的可变性(外部拿到引用后能修改元素)有时候会带来隐患,换成List的话,可以用Collections.unmodifiableList封装成不可变集合,同时在构造时强制元素数量为4:
import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Objects; public class QAData { private final String question; private final List<String> options; private final List<Boolean> answerFlags; private final List<Boolean> selectedFlags; public QAData(String question, List<String> options, List<Boolean> answerFlags, List<Boolean> selectedFlags) { this.question = Objects.requireNonNull(question); // 校验每个List的元素数量必须为4 validateListLength(options, "可选答案列表"); validateListLength(answerFlags, "正误标记列表"); validateListLength(selectedFlags, "用户选中标记列表"); // 封装成不可变列表,彻底防止外部修改内部数据 this.options = Collections.unmodifiableList(new ArrayList<>(options)); this.answerFlags = Collections.unmodifiableList(new ArrayList<>(answerFlags)); this.selectedFlags = Collections.unmodifiableList(new ArrayList<>(selectedFlags)); } private void validateListLength(List<?> list, String listName) { if (list == null || list.size() != 4) { throw new IllegalArgumentException(listName + "必须包含恰好4个元素"); } } // Getter直接返回不可变List即可 public List<String> getOptions() { return options; } }
这种方式的可读性更好,而且不可变List能完全避免外部篡改内部数据的问题。
3. 直接定义单独字段(最彻底的方案)
既然需求是固定4个选项,那干脆不用数组/List,直接定义4个单独的字段。这样从根源上就不存在“长度不符合”的问题,代码可读性也拉满:
import java.util.Objects; public class QAData { private final String question; private final String option1; private final String option2; private final String option3; private final String option4; private final boolean answerFlag1; private final boolean answerFlag2; private final boolean answerFlag3; private final boolean answerFlag4; private boolean selectedFlag1; private boolean selectedFlag2; private boolean selectedFlag3; private boolean selectedFlag4; public QAData(String question, String option1, String option2, String option3, String option4, boolean answerFlag1, boolean answerFlag2, boolean answerFlag3, boolean answerFlag4) { this.question = Objects.requireNonNull(question); // 可以额外校验每个选项不为空 this.option1 = Objects.requireNonNull(option1); this.option2 = Objects.requireNonNull(option2); this.option3 = Objects.requireNonNull(option3); this.option4 = Objects.requireNonNull(option4); this.answerFlag1 = answerFlag1; this.answerFlag2 = answerFlag2; this.answerFlag3 = answerFlag3; this.answerFlag4 = answerFlag4; // 初始选中状态默认设为false,也可以改成传入参数 this.selectedFlag1 = false; this.selectedFlag2 = false; this.selectedFlag3 = false; this.selectedFlag4 = false; } // 选中标记的getter和setter(按需实现) public boolean isSelectedFlag1() { return selectedFlag1; } public void setSelectedFlag1(boolean selectedFlag1) { this.selectedFlag1 = selectedFlag1; } // 其他字段的getter/setter同理实现... }
虽然字段数量多了点,但完全不需要担心长度问题,后续维护的时候也能一眼看懂每个字段的含义。
4. Java 16+用Record类(简洁版)
如果你的项目用的是Java 16及以上版本,可以用Record类结合紧凑构造器来快速实现,代码更简洁,同时自带不可变性:
import java.util.Arrays; import java.util.Objects; public record QAData(String question, String[] options, boolean[] answerFlags, boolean[] selectedFlags) { // Record的紧凑构造器,用于校验和处理数据 public QAData { Objects.requireNonNull(question, "问题文本不能为null"); if (options == null || options.length != 4) { throw new IllegalArgumentException("可选答案数组必须长度为4"); } if (answerFlags == null || answerFlags.length != 4) { throw new IllegalArgumentException("正误标记数组必须长度为4"); } if (selectedFlags == null || selectedFlags.length != 4) { throw new IllegalArgumentException("用户选中标记数组必须长度为4"); } // 同样做防御性拷贝 options = Arrays.copyOf(options, 4); answerFlags = Arrays.copyOf(answerFlags, 4); selectedFlags = Arrays.copyOf(selectedFlags, 4); } }
Record类会自动生成equals、hashCode、toString和getter方法,非常适合这种纯数据载体的场景。
内容的提问来源于stack exchange,提问作者laurie
相关产品推荐
相关产品推荐

