首页 > 其他分享 >Groovy StringBuilder类踩坑

Groovy StringBuilder类踩坑

时间:2023-12-06 23:04:51浏览次数:29  
标签:Groovy java StringBuilder 报错 sb setLength

今天在写脚本的时候发现一个奇怪的错误。经过猜想验证,发现原来Groovy过于灵活了,算是重复踩了之前的坑。Groovy特性描述如下:

当Groovy脚本调用getFun()和setFun()方法时,会默认给这个类有一个FunTester的属性。反过来,如果这个类有Fun这个属性,那么get和set方法是不用显式写出来的。

本来这是个好事情,一方面其实可以免去多余代码,一方面更容易收拢入口方法(因为直接访问属性、修改属性也是有限调用get和set方法)。

但是就是这个特性让我下面的代码报错了。

        StringBuilder sb = new StringBuilder()
        for (int i = 0; i < 3; i++) {
            sb.append("a" + i)
            output(sb.toString())
            sb.setLength(0)
        }

其中java.lang.AbstractStringBuilder#setLength方法是用来裁剪StringBuilder对象内容的,如果参数为0,实际的功效就是清空。

官方的描述为:

setLength(int newLength)AbstractStringBuilder 类中的一个方法,用于设置字符串的长度。具体来说,它有以下作用:

  • 如果 newLength 小于当前字符串的长度,则字符串将被截断为指定的长度 newLength
  • 如果 newLength 大于当前字符串的长度,则在字符串末尾填充空字符('\0')直到字符串达到指定的长度 newLength

下面是我代码报错信息:

No signature of method: java.lang.StringBuilder.setLength() is applicable for argument types: (Integer) values: [0]
	at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:70)
	at org.codehaus.groovy.runtime.callsite.PojoMetaClassSite.call(PojoMetaClassSite.java:46)
	at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:139)

错误信息显示并没有这个方法,真是见了鬼了,我在Intellij里面查看源码时明明显示没有问题。当我把问题抛给ChatGPT,得到如下回答。

这个错误信息是Groovy中的一个问题,可能是因为Groovy与Java在StringBuilder类的操作上存在某些不同。setLength()方法通常用于设置StringBuilder的长度,但是错误信息表明setLength()方法似乎被错误地调用,传递了一个不正确的参数类型。在Java中,setLength()方法接受一个int类型的参数,表示要设置的新长度。但是在错误信息中显示传递了Integer类型的值 [0],这可能导致方法调用失败。如果问题仍然存在,可能需要进一步检查Groovy代码中的其他部分,以确保在StringBuilder操作方面没有其他的语法错误或问题。

这个时候我才意识到这是一个Groovy的报错,并不是Java的。所以,根据我多年踩坑经验早就的敏感度,set方法一定是出问题了。经过我检查,StringBuilder类并没有length属性,这就是导致报错的根本原因。

下面我来验证自己的猜想,通过Groovy元编程给StringBuilder类加上这个length属性。

        StringBuilder.metaClass.length= 32
        StringBuilder sb = new StringBuilder()
        for (int i = 0; i < 3; i++) {
            sb.append("a" + i)
            output(sb.toString())
            sb.setLength(0)
        }

这下不报错了,但问题来了,setLength功能不起作用了,因为优先去设置属性值去了。看来虽然验证了,但是功能破坏了,只好用点笨办法了。

        StringBuilder.metaClass.length= 32
        StringBuilder sb = new StringBuilder()
        for (int i = 0; i < 3; i++) {
            sb.append("a" + i)
            output(sb.toString())
        }

这个就解决了所有问题。当我去用Java代码中验证时,发现一直没有报错。我换了个项目(Maven/Gradle)结果发现居然无法复现了。哎,又遇到幽灵的问题,可能Groovy在编译这个项目类的时候开小差了。我的JDK版本17,Groovy编译插件版本3.0.1,重新清空本地缓存重启Intellij也依然如此。 通过对比两个项目差异,同时升级Groovy依赖版本和编译插件版本,改缺陷自动解决了。

标签:Groovy,java,StringBuilder,报错,sb,setLength
From: https://blog.51cto.com/FunTester/8711109

相关文章

  • Groovy学习
    一、数据类型下面的是内置数据类型,一旦定义后无法修改变量类型1byte-这是用来表示字节值。例如2。2short-这是用来表示一个短整型。例如10。3int-这是用来表示整数。例如1234。4long-这是用来表示一个长整型。例如10000090。5float-这是用来表示32位浮点数。例如......
  • 为什么 idea 建议去掉 StringBuilder,使用“+”拼接字符串
    为什么idea建议去掉StringBuilder,使用“+”拼接字符串目录为什么idea建议去掉StringBuilder,使用“+”拼接字符串1、普通拼接2、循环拼接总结各位小伙伴在字符串拼接时应该都见过下面这种提示:内容翻译:报告StringBuffer、StringBuilder或StringJoiner的任何用法,这些用法......
  • gradle和groovy
    what:一种JVM语言,它可以编译为与Java相同的字节码,然后将字节码文件交给JVM去执行,Groovy是并且可以与Java类无缝地互操作,Groovy可以透明地与Java库和代码交互,可以使用Java所有的库。Groovy也可以直接将源文件解释执行。 how:......
  • 为什么 IDEA 建议去掉 StringBuilder,而要使用 “+” 拼接字符串?
    作者:京东零售姜波来源:京东云开发者社区各位小伙伴在字符串拼接时应该都见过下面这种提示:内容翻译:报告StringBuffer、StringBuilder或StringJoiner的任何用法,这些用法可以用单个java.lang.String串联来替换。使用字符串串联可以使代码更短、更简单。只有当得到的串联至少与原......
  • 【Java基础】String类 && StringBuilder类
    String类String类特点字符串底层是字节类型的数组:byte[]Java程序中所有双引号字符串,都是String类的实例(对象)字符串在创建之后,其内容不可更改字符串虽然不可以改变,但是可以被共享(通过字符串常量池)字符串常量池(StringTable)-->当使用双引号创建字符串对象时,会检查常量池中是......
  • java中String、StringBuffer和StringBuilder的区别(简单介绍)
    简单介绍java中用于处理字符串常用的有三个类:1、java.lang.String2、java.lang.StringBuffer3、java.lang.StrungBuilder三者共同之处:都是final类,不允许被继承,主要是从性能和安全性上考虑的,因为这几个类都是经常被使用着,且考虑到防止其中的参数被参数修改影响到其他的应用......
  • java(StringBuilder)练习
    需求:键盘录入一个九位数以下的数字将该数字各数字变为罗马数字。importjava.util.Scanner;publicclassBoke{publicstaticvoidmain(String[]args){ScannerSc=newScanner(System.in);Stringx;while(true){System.out.......
  • java StringBuilder对象和StringJoiner
    普及:因为StringBuilder是Java已经写好的类java在底层对他做了一些特殊处理。打印对象不是地址值而是属性值。packagecom.elaina.test2;publicclasstest10{publicstaticvoidmain(String[]args){//1.创建对象StringBuildersb=newSt......
  • Groovy初学者指南
    本文已收录至GitHub,推荐阅读......
  • 包装类、StringBuilder、StringBuffer、StringJoiner
    1、怎么将Int类型的包装成对象使用Integer的valueOf方法Integera2==Integer.valueOf(12);2、自动装箱机制(可以自动把基本数据类型的数据转换成对象)Integera3=12;自动拆箱机制(可以自动把包装类型的对象转换成对应的基本数据类型)inta4=a3;......