Lombok HandlerGetter 解析

Lombok的@Getter注解可以在编译时自动为对象属性添加getter方法,以减少冗余代码。本文详细介绍了@Getter的处理规则:1. 若已有自定义getter方法,Lombok将不再生成新的getter;2. 布尔类型字段以is开头会生成isXXX()方法;3. 非布尔is开头字段,首字母会变大写。在实际开发中,Lombok的getter生成规则可能与Jackson序列化规则不一致,导致字段名称转换问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

通过lombok  @Getter注解可以减少代码中对象属性getter方法的冗余,而lombok在编译时期会对增加@Getter注解的属性添加相应的getter方法,其对@Getter处理实现类为HandlerGetter.java,如下是使用@Getter后的几个注意事项。

 

1.lombok  @Getter会优先使用对象类中存在的getter()方法。

 

for (String altName : toAllGetterNames(fieldNode)) {

   switch (methodExists(altName, fieldNode, false0)) {

   case EXISTS_BY_LOMBOK:

      return;

   case EXISTS_BY_USER:

      if (whineIfExists) {

         String altNameExpl = "";

         if (!altName.equals(methodName)) altNameExpl = String.format(" (%s)", altName);

         source.addWarning(

            String.format("Not generating %s(): A method with that name already exists%s", methodName, altNameExpl));

      }

      return;

   default:

   case NOT_EXISTS:

      //continue scanning the other alt names.

   }

}

 

long access = toJavacModifier(level) | (fieldDecl.mods.flags & Flags.STATIC);

 

injectMethod(fieldNode.up(), createGetter(access, fieldNode, fieldNode.getTreeMaker(), source.get(), lazy, onMethod), List.<Type>nil(), getMirrorForFieldType(fieldNode));

从上面可以看到如果用户提供了getter方法,即case EXISTS_BY_USER,则不再为此field创建新的getter方法。

 

2.布尔类型(boolean  注意boolean 不等同Boolean)is开头生成Getter方法

private static String toAccessorName(AST<?, ?, ?> ast, AnnotationValues<Accessors> accessors, CharSequence fieldName, boolean isBoolean,

      String booleanPrefix, String normalPrefix, boolean adhereToFluent) {

    

   fieldName = fieldName.toString();

   if (fieldName.length() == 0return null;

    

   if (Boolean.TRUE.equals(ast.readConfiguration(ConfigurationKeys.GETTER_CONSEQUENT_BOOLEAN))) isBoolean = false;

   boolean explicitPrefix = accessors != null && accessors.isExplicit("prefix");

   boolean explicitFluent = accessors != null && accessors.isExplicit("fluent");

    

   Accessors ac = (explicitPrefix || explicitFluent) ? accessors.getInstance() : null;

    

   List<String> prefix = explicitPrefix ? Arrays.asList(ac.prefix()) : ast.readConfiguration(ConfigurationKeys.ACCESSORS_PREFIX);

   boolean fluent = explicitFluent ? ac.fluent() : Boolean.TRUE.equals(ast.readConfiguration(ConfigurationKeys.ACCESSORS_FLUENT));

    

   fieldName = removePrefix(fieldName, prefix);

   if (fieldName == nullreturn null;

    

   String fName = fieldName.toString();

   if (adhereToFluent && fluent) return fName;

    

   if (isBoolean && fName.startsWith("is") && fieldName.length() > 2 && !Character.isLowerCase(fieldName.charAt(2))) {

      // The field is for example named 'isRunning'.

      return booleanPrefix + fName.substring(2);

   }

    

   return buildAccessorName(isBoolean ? booleanPrefix : normalPrefix, fName);

}

以上suffix为字段名,booleanPrefix为is,可以看到是布尔类型的字段,且以is开头,第三个字母小写则生成的方法为isXXX(),否则走注意事项三, 如果一个布尔类型的字段如isrunning执行事项三,则此时其prefix 为is,则生成的方法为isIsrunning。
 

3.非布尔is开头字段生成Getter方法,则会把首字母变成大写。

public static String buildAccessorName(String prefix, String suffix) {

   if (suffix.length() == 0return prefix;

   if (prefix.length() == 0return suffix;

    

   char first = suffix.charAt(0);

   if (Character.isLowerCase(first)) {

      boolean useUpperCase = suffix.length() > 2 &&

         (Character.isTitleCase(suffix.charAt(1)) || Character.isUpperCase(suffix.charAt(1)));

      suffix = String.format("%s%s",

            useUpperCase ? Character.toUpperCase(first) : Character.toTitleCase(first),

            suffix.subSequence(1, suffix.length()));

   }

   return String.format("%s%s", prefix, suffix);

}

以上suffix为字段名,prefix为get,可以看到如果field名称首字母大写,例如Axxx那么生成的getter方法为getAxxx(), 如果首字母小写可以看到其把首字母变成了大写。

 

根据以上所述我们可以看下通过lombok生成的getter方法的一个类

 

源文件:

@Getter

private static class LombokGetter{

  private boolean isRunning;// 对应注意事项2

  private boolean isrunning;//对应注意事项2,3

  private Boolean isStop;//对应注意事项3

  private String yAxises;//对应注意事项3

 

}

 

编译后文件

 private static class LombokGetter

  {

    private boolean isRunning;

    private boolean isrunning;

    private Boolean isStop;

    private String yAxises;

     

    public boolean isRunning()

    {

      return this.isRunning;

    }

     

    public boolean isIsrunning()

    {

      return this.isrunning;

    }

     

    public Boolean getIsStop()

    {

      return this.isStop;

    }

     

    public String getYAxises()

    {

      return this.yAxises;

    }

  }

 

 

下面我们看下在开发中我们遇到的几个问题

public static void main(String[] args) throws Exception{

 System.out.println(new ObjectMapper().writeValueAsString(new LombokGetter()));

}

 

@Getter

private static class LombokGetter{

  private boolean isRunning;// 对应注意事项2

  private boolean isrunning;//对应注意事项2,3

  private Boolean isStop;//对应注意事项2,3

  private String yAxises;//对应注意事项3

}

print:

{"isrunning":false,"isStop":null,"running":false,"yaxises":null}

针对yaxises我们可能更想得到yAxisses,但是经过jackon处理后得到的是yaxises,在编译文件中我们可以看到其get方法为getYAxises();

经过jackson处理后得到的是yaxises

protected static String legacyManglePropertyName(final String basename, final int offset)

{

    final int end = basename.length();

    if (end == offset) { // empty name, nope

        return null;

    }

    // next check: is the first character upper case? If not, return as is

    char c = basename.charAt(offset);

    char d = Character.toLowerCase(c);

     

    if (c == d) {

        return basename.substring(offset);

    }

    // otherwise, lower case initial chars. Common case first, just one char

    StringBuilder sb = new StringBuilder(end - offset);

    sb.append(d);

    int i = offset+1;

    for (; i < end; ++i) {

        c = basename.charAt(i);

        d = Character.toLowerCase(c);

        if (c == d) {

            sb.append(basename, i, end);

            break;

        }

        sb.append(d);

    }

    return sb.toString();

}

代码中offset为3,basename为getYAxises,可以看到最后生成的name 为yaxises,其是从第四个字符开始转化成小写字符,直到遇到小写字母终止,jackson默认采用上面的方式生成name,当然还可以配置其他方式,将在jackson篇幅进行介绍。

 

因此综上所述个人认为lombok对注意事项二,注意事项三的处理并不是lombok的bug,只不过其规约没有和jackson的序列化规约一致。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值