You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Scala继承Java类重写成员时Pattern编译获null值问题求助

问题根源

父类A的构造函数中调用了可被重写的getRegex()方法,而Scala子类B的初始化流程是:先执行父类构造,再初始化子类成员。当父类构造调用getRegex()时,B中的val regex还未完成赋值(此时值为null),导致Pattern.compile(null)拿到无效值。

解决方案

若可修改父类A

1. 构造参数传入正则表达式

重构Java父类,直接通过构造参数接收regex,避免依赖重写方法:

import java.util.regex.Pattern;

class A { 
    private final Pattern pattern;
    private final String regex;

    A(String regex) { 
       this.regex = regex;
       this.pattern = Pattern.compile(this.regex);
    }
    
    public String getRegex() {
        return regex;
    }
}

Scala子类直接传入自定义正则:

class B(...) extends A("folder4/.*") {
    // 仅当需要额外逻辑时重写,否则可省略
    override def getRegex(): String = super.getRegex()
}

2. 延迟初始化Pattern

将Pattern改为懒加载,避免在父类构造时调用重写方法:

import java.util.regex.Pattern;
import java.util.function.Supplier;

class A { 
    private final Supplier<Pattern> patternSupplier;
    private String regex = "folder1/folder2/folder3/.*";

    A(...) { 
       this.regex = regex;
       this.patternSupplier = () -> Pattern.compile(getRegex());
    }
    
    public Pattern getPattern() {
        return patternSupplier.get(); // 第一次调用时才编译
    }
    
    public String getRegex() {
        return regex;
    }
}

这种方式下,父类构造不会立即执行getRegex(),等到子类完全初始化后,第一次调用getPattern()时才会编译正则,此时B的regex已经赋值完成。

若无法修改父类A

1. 使用Scala提前初始化块

通过提前初始化语法,让B的regex在父类构造前完成赋值:

class B(...) extends {
    // 此块在父类构造执行前初始化成员
    val regex: String = "folder4/.*"
} with A(...) {
    override def getRegex(): String = regex
}

2. 使用lazy val延迟初始化

将regex声明为lazy val,第一次调用getRegex()时才初始化它:

class B(...) extends A(...) {
    lazy val regex: String = "folder4/.*"
    
    override def getRegex(): String = regex
}

注意:此方式要求lazy val的初始化逻辑不依赖其他未初始化的子类成员,否则可能引发新问题。

内容的提问来源于stack exchange,提问作者Good Panic

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 00:55:16