Java静态类中生成常量Note数组及解决元素为null的实现方法
问题根因
你当前使用的是实例初始化块,只有在Constants类被实例化的时候才会执行,而作为常量类的Constants通常不会被实例化,所以数组填充逻辑从未运行,元素自然全为null。同时你贴的原始代码里for循环的闭合大括号写错,也会导致编译异常。
修复方案
方案1:改用静态初始化块
直接给初始化块添加static修饰符,会在Constants类加载时自动执行填充逻辑,符合常量类的加载逻辑:
public class Note{ // 其他Note类逻辑省略 public static class Constants{ public static final int lowestOctave = 0; public static final int highestOctave = 8; public static final int numOfOctaves = highestOctave + 1; public static final int numOfNotes = numOfOctaves * 12; public static final Note[] allNotesArray = new Note[numOfNotes]; // 静态初始化块,类加载时自动执行 static { for(int i = 0; i < numOfNotes; i++){ allNotesArray[i] = new Note(/* 填入你的Note构造参数 */); } } // 私有构造方法,禁止常量类被实例化,符合设计规范 private Constants(){} } }
方案2:延迟加载+返回不可变副本(更安全)
如果不需要类加载就初始化数组,要用到时再触发,同时避免外部代码修改常量数组的元素,可以用封装的静态方法实现:
import java.util.Arrays; public static class Constants{ public static final int lowestOctave = 0; public static final int highestOctave = 8; public static final int numOfOctaves = highestOctave + 1; public static final int numOfNotes = numOfOctaves * 12; private static Note[] allNotesArray; // 对外只提供获取方法,不直接暴露数组 public static Note[] getAllNotes() { // 双重校验锁实现线程安全的延迟初始化 if (allNotesArray == null) { synchronized (Constants.class) { if (allNotesArray == null) { allNotesArray = new Note[numOfNotes]; for(int i = 0; i < numOfNotes; i++){ allNotesArray[i] = new Note(/* 构造参数 */); } } } } // 返回数组副本,避免外部修改原常量数组的元素 return Arrays.copyOf(allNotesArray, allNotesArray.length); } private Constants(){} }
更简洁的写法(Java 8+)
用Stream流直接生成数组,代码更精简:
public static final Note[] allNotesArray = IntStream.range(0, numOfNotes) .mapToObj(i -> new Note(/* 用i计算对应的八度、音高参数 */)) .toArray(Note[]::new);
内容的提问来源于stack exchange,提问作者George Yeatman
相关产品推荐
相关产品推荐

