Lombok Builder能否流畅调用?链式调用静态方法报错问题
我需要根据运行时传入的字段名填充对象,因此使用Lombok的@Builder注解创建了MyClass,并编写了静态方法setFieldValue,通过反射为Builder实例设置对应字段值,方法返回传入的Builder实例。但在Main类中链式调用该静态方法时,出现编译错误:IDE提示MyClassBuilder中无法解析setFieldValue方法,报错信息为java: cannot find symbol...。
相关代码
MyClass.java
import lombok.Builder; import lombok.ToString; import java.lang.reflect.Method; @Builder @ToString public class MyClass { private String field1; private int field2; private boolean field3; public static MyClassBuilder setFieldValue(MyClassBuilder builder, String fieldName, Object fieldValue) throws Exception { Class<?> builderClass = builder.getClass(); Method setterMethod = null; for (Method method : builderClass.getDeclaredMethods()) { if (method.getName().equalsIgnoreCase(fieldName)) { setterMethod = method; break; } } if (setterMethod != null) { setterMethod.invoke(builder, fieldValue); } return builder; } }
Main.java
public class Main { public static void main(String[] args) throws Exception { MyClass.MyClassBuilder builder = MyClass.builder(); MyClass myObject = MyClass.setFieldValue(builder, "field1", "Hello") .setFieldValue(builder, "field2", 123) .setFieldValue(builder, "field3", true) .build(); System.out.println(myObject); } }
报错信息
java: cannot find symbol symbol: method setFieldValue(MyClass.MyClassBuilder,java.lang.String,int) location: class MyClass.MyClassBuilder
核心问题
你犯了链式调用的语法错误:第一次调用MyClass.setFieldValue(builder, ...)返回的是MyClassBuilder实例,但后续的.setFieldValue(...)是在这个Builder实例上调用的——而setFieldValue是MyClass的静态方法,并不是MyClassBuilder的成员方法,因此编译器找不到这个方法。
方法1:显式重复调用静态方法
每次调用都通过MyClass类来调用静态方法,把前一次返回的Builder实例作为参数传入:
MyClass myObject = MyClass.setFieldValue( MyClass.setFieldValue( MyClass.setFieldValue(builder, "field1", "Hello"), "field2", 123), "field3", true) .build();
方法2:给Builder添加成员方法(推荐)
手动扩展Lombok生成的内部Builder类,添加成员方法版的setFieldValue,这样就能支持链式调用:
修改后的MyClass代码:
import lombok.Builder; import lombok.ToString; import java.lang.reflect.Method; @Builder @ToString public class MyClass { private String field1; private int field2; private boolean field3; // 可选:保留静态方法,内部转发给Builder的成员方法 public static MyClassBuilder setFieldValue(MyClassBuilder builder, String fieldName, Object fieldValue) throws Exception { return builder.setFieldValue(fieldName, fieldValue); } // 扩展Lombok生成的Builder类,添加成员方法 public static class MyClassBuilder { public MyClassBuilder setFieldValue(String fieldName, Object fieldValue) throws Exception { Class<?> builderClass = this.getClass(); Method setterMethod = null; for (Method method : builderClass.getDeclaredMethods()) { // Lombok Builder的set方法名与字段名完全一致(如field1对应field1()) if (method.getName().equalsIgnoreCase(fieldName)) { setterMethod = method; break; } } if (setterMethod != null) { setterMethod.invoke(this, fieldValue); } return this; } } }
修改后的Main类链式调用代码:
public class Main { public static void main(String[] args) throws Exception { MyClass myObject = MyClass.builder() .setFieldValue("field1", "Hello") .setFieldValue("field2", 123) .setFieldValue("field3", true) .build(); System.out.println(myObject); } }
额外提示
Lombok生成的Builder方法名与字段名完全一致(例如字段field1对应方法field1(...)),你的反射匹配逻辑是正确的,但如果字段名是驼峰格式,注意equalsIgnoreCase可能会匹配到不相关的方法,建议严格匹配字段名(去掉equalsIgnoreCase),避免意外问题。
内容的提问来源于stack exchange,提问作者amadain

