
当抽象父类中定义了protected修饰的静态抽象builder类时,外部测试类无法访问其build()方法;解决方法是将builder类的访问修饰符改为public,确保子类builder可被外部代码实例化和调用。
当抽象父类中定义了protected修饰的静态抽象builder类时,外部测试类无法访问其build()方法;解决方法是将builder类的访问修饰符改为public,确保子类builder可被外部代码实例化和调用。
在使用Builder模式构建测试验证器(如 GetCommentExpectationTester)时,若父类 AbstractGetCommentExpectationTester 中将嵌套的 Builder 类声明为 protected abstract static class Builder,会导致一个关键限制:该 Builder 类仅对同包内类或其子类可见,但不可被外部测试类直接引用或实例化。
具体到您的代码中:
protected abstract static class Builder { /* ... */ }虽然 GetCommentExpectationTester.Builder 正确继承了该抽象类,并实现了 build() 方法,但测试方法中这行代码:
expectationTester = new GetCommentExpectationTester.Builder(response)
.setExpectedOwnerUsername("mickey")
.build(); // 编译报错:Cannot access 'build()' in '...AbstractGetCommentExpectationTester.Builder'会失败——根本原因在于:AbstractGetCommentExpectationTester.Builder 是 protected 的,因此 GetCommentExpectationTester.Builder 尽管是它的子类,其构造器和继承关系对外部类(如测试类)而言仍是不可见的。编译器无法确认 new GetCommentExpectationTester.Builder(...) 的合法性,进而拒绝解析 .build() 调用。
立即学习“Java免费学习笔记(深入)”;
✅ 正确解法:将父类中的 Builder 声明提升为 public:
public abstract static class Builder { // ← 关键修改:从 protected 改为 public
protected final String serializedResponseBody;
// ... 其余字段与方法保持不变
protected Builder(MockHttpServletResponse response) throws UnsupportedEncodingException {
this.serializedResponseBody = response.getContentAsString();
}
public Builder setExpectedOwnerUsername(String expectedOwnerUsername) {
this.expectedOwnerUsername = expectedOwnerUsername;
return this;
}
// 注意:build() 仍为 abstract,由子类实现
public abstract AbstractGetCommentExpectationTester build();
}同时,子类 GetCommentExpectationTester.Builder 也需确保构造器为 public(当前已是):
public static class Builder extends AbstractGetCommentExpectationTester.Builder {
public Builder(MockHttpServletResponse response) throws UnsupportedEncodingException {
super(response);
}
@Override
public GetCommentExpectationTester build() {
return new GetCommentExpectationTester(this);
}
}⚠️ 注意事项:
- protected 类型的嵌套类不能被包外非子类访问,即使子类已将其暴露为 public static class,其父类 Builder 的可见性仍是瓶颈;
- public abstract static class Builder 是标准 Builder 模式在继承体系中的推荐写法,兼顾封装性与可扩展性;
- 若项目有严格包访问控制需求,也可将测试类与抽象基类置于同一包下(不推荐,破坏模块边界),但 public 修饰符是最清晰、最符合 Java 访问控制语义的解决方案。
修改后,测试代码即可正常编译并运行,Builder 链式调用完全可用,抽象层次带来的复用优势得以充分发挥。


















