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
相关产品推荐
相关产品推荐

