在一个类的构造器还未执行之前,我们无法使用这个类的成员
百度翻译:在调用超类型构造函数之前无法引用“XxxClass.xxx” ----- 我的理解:在一个类的构造器方法还未执行的时候,我们无法使用这个类的成员属性或成员方法。
下面是会出现此错误的示例代码
public class MyException extends RuntimeException { private int errorCode = 0; public MyException(String message) { super(message + getErrorCode()); // compilation error } public int getErrorCode() { return errorCode; } }
IDE提示错误:Cannot reference 'MyException.getErrorCode' before supertype constructor has been called
.
说说我怎么遇到这个问题的?
我有一个组件工具类。
1 @Slf4j 2 public class Many2OneProcessor<T> { 3 4 private static ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(15); 5 6 /** 7 * 将多长时间的多次操作合并成1次,单位:秒 8 */ 9 private final long intervalSecond; 10 /** 11 * 每次处理多少条数据 12 */ 13 private final int perBatchCount; 14 /** 15 * 批次处理逻辑代码 16 */ 17 private final Consumer<List<T>> yourBusinessCode; 18 private final ... 19 20 public Many2OneProcessor(long intervalSecond, Class<T> tClass, Consumer<List<T>> yourBusinessCode) { 21 this(intervalSecond, Integer.MAX_VALUE, tClass, yourBusinessCode); 22 } 23 24 public Many2OneProcessor(long intervalSecond, int perBatchCount, Class<T> tClass, Consumer<List<T>> yourBusinessCode) { 25 26 ...此处省略若干行 27 28 } 29 30 public void produce(T t) { 31 redisUtil.lSet(LIST_KEY, t, HOURS.toMillis(1)); 32 scheduledThreadPool.schedule(this::consumeMsg, intervalSecond, TimeUnit.SECONDS); 33 } 34 35 private void consumeMsg() { 36 redisLockTemplate.execute(LOCK_KEY, TimeUnit.SECONDS.toMillis(intervalSecond - 1), false, () -> { 37 38 ...此处省略若干行 39 40 List<T> tList = new ArrayList<>(perBatchCount + 1); 41 for (int j = 0; j < perBatchCount; j++) { 42 Object o = redisUtil.lPop(LIST_KEY); 43 if (o == null) break; 44 tList.add((T) o); 45 } 46 if (perBatchCount != Integer.MAX_VALUE && redisUtil.lGetListSize(LIST_KEY) > 0) { 47 scheduledThreadPool.schedule(this::consumeMsg, intervalSecond, TimeUnit.SECONDS); 48 } 49 50 ...此处省略若干行 51 yourBusinessCode.accept(tList); 52 53 }); 54 } 55 }
注意到其中的两处 Integer.MAX_VALUE,这无形中提高了代码理解和维护(重点是前者)的成本。
于是,做个小小的重构。改为下面这样,代码的可理解方面,更上一层楼。
public class Many2OneProcessor<T> { /** * 每次处理多少条数据 */ private final int perBatchCount; private static final int PER_BATCH_COUNT_DEFAULT = Integer.MAX_VALUE; public Many2OneProcessor(long intervalSecond, Class<T> tClass, Consumer<List<T>> yourBusinessCode) { this(intervalSecond, PER_BATCH_COUNT_DEFAULT, tClass, yourBusinessCode); } public void consumeMsg() { ... if (perBatchCount != PER_BATCH_COUNT_DEFAULT && redisUtil.lGetListSize(LIST_KEY) > 0) { ... } }
注意,常量 PER_BATCH_COUNT_DEFAULT 定义为static,否则会出现上面的预编译错误:Cannot reference 'Many2OneProcessor.PER_BATCH_COUNT_DEFAULT' before supertype constructor has been called
。另外,在重构过程中,我使用了一种方案,见下图,也出现了这个错误:Cannot reference 'Many2OneProcessor.perBatchCount' before supertype constructor has been called
后记:邂逅OutOfMemoryError
自测时发现,上面代码在某些case下会执行List<T> tList = new ArrayList<>(Integer.MAX_VALUE+1);
,由于Integer.MAX_VALUE+1
是负数,程序会抛出异常:java.lang.IllegalArgumentException: Illegal Capacity: -2147483648
另外,如果把上面代码行改为List<T> tList = new ArrayList<>(Integer.MAX_VALUE);
,则会抛出:java.lang.OutOfMemoryError: Requested array size exceeds VM limit。继续挣扎,试图改为List<T> tList = new ArrayList<>(Integer.MAX_VALUE/2);
,亦会抛出:java.lang.OutOfMemoryError: Java heap space文章来源:https://www.toymoban.com/news/detail-484636.html
当未指定perBatchCount参数值时,将其默认值指定为Integer.MAX_VALUE
实在欠合理!结合使用场景评定后,将上面的阈值PER_BATCH_COUNT_DEFAULT改为99999。文章来源地址https://www.toymoban.com/news/detail-484636.html
到了这里,关于Cannot Reference “XxxClass.xxxmember” Before Supertype Constructor Has Been Called的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!