关于 Stringbuilder 中 append 方法的实现有一个疑问 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
zhao1014
V2EX    Java

关于 Stringbuilder 中 append 方法的实现有一个疑问

  •  
  •   zhao1014 2022-06-14 12:19:13 +08:00 2724 次点击
    这是一个创建于 1280 天前的主题,其中的信息可能已经有所发展或是发生改变。
    public AbstractStringBuilder append(String str) { // 如果 str 为 null ,则在字符数组中添加 'n''u''l''l' if (str == null) return appendNull(); int len = str.length(); ensureCapacityInternal(count + len); str.getChars(0, len, value, count); count += len; return this; }``` 字符串参数为 null 时调用了 appendNull(); 方法 ```java private AbstractStringBuilder appendNull() { int c = count; ensureCapacityInternal(c + 4); // 这里将内部字符数组赋值给局部变量 final char[] value = this.value; // 然后通过局部变量向内部数组添加字符 value[c++] = 'n'; value[c++] = 'u'; value[c++] = 'l'; value[c++] = 'l'; // 这里的 count 也是先赋值给局部变量,为什么不直接使用 count 呢? count = c; return this; }``` 我的疑问是 appendNull 方法中为什么要创建一个 final char[] value 这样一个局部变量来操作内部数组而不是直接使用 this.value ?这么做的用意是什么?
    18 条回复    2022-06-23 09:55:59 +08:00
    GuuJiang
        1
    GuuJiang  
       2022-06-14 12:22:12 +08:00 via iPhone   1
    不这样的话下面的每一行代码都要写成 this.value[c++],对应的 opcode 要多一次 get_field 操作
    chendy
        2
    chendy  
       2022-06-14 12:23:29 +08:00   1
    压榨性能
    可以省下后续用 this 找 value 的开销
    zhao1014
        3
    zhao1014  
    OP
       2022-06-14 12:51:58 +08:00
    还是有点不理解,写成这样的话也不用 this 调用了啊
    ```java
    private AbstractStringBuilder appendNull() {

    ensureCapacityInternal(c + 4);

    value[count++] = 'n';
    value[count++] = 'u';
    value[count++] = 'l';
    value[count++] = 'l';

    return this;
    }
    zhao1014
        4
    zhao1014  
    OP
       2022-06-14 12:53:14 +08:00
    使用实例变量调用跟使用局部变量调用的区别在哪呢?不太明白
    zhao1014
        5
    zhao1014  
    OP
       2022-06-14 12:54:50 +08:00
    除了多线程的问题以外想不到区别了:(
    TWorldIsNButThis
        6
    TWorldIsNButThis  
       2022-06-14 13:30:10 +08:00 via iPhone   1
    直接找 count 是在堆上找
    你在栈上声明一遍下面用的地方就是从栈上直接拿
    mxalbert1996
        7
    mxalbert1996  
       2022-06-14 13:40:11 +08:00 via Android   1
    @zhao1014
    使用局部变量比取得 4 次成员变量要更高效。
    在这里 `value` 和 `this.value` 完全等价,字节码也不会有任何区别。
    skinny
        8
    skinny  
       2022-06-14 13:42:04 +08:00
    可以少打几十个字符而已,JVM 不至于这么蠢这么简单的代码都不会优化。
    kiroter
        9
    kiroter  
       2022-06-14 13:43:04 +08:00
    习惯问题,查看引用的时候会少很多。get 什么编译器应该会优化的
    liyunyang
        10
    liyunyang  
       2022-06-14 13:53:28 +08:00   1
    final char[] value 定义后在堆上会有固定的 value 指向(无法修改引用地址)
    下次再进来的时候可以直接用
    maokabc
        11
    maokabc  
       2022-06-14 14:00:43 +08:00 via Android   2
    用 javap 看字节码就可以发现区别,就是 gefield 指令比 aload 、iload 这类指令开销大,更别说 getfield 之前还有一条 aload_0 指令先得到 this 。
    cubecube
        12
    cubecube  
       2022-06-14 17:02:08 +08:00
    @skinny 字节码层面,真不会优化。。别把 jvm 想得太高级。jit 层面未来没准会吧
    huyangq
        13
    huyangq  
       2022-06-14 17:09:46 +08:00
    11 楼正解
    GuuJiang
        14
    GuuJiang  
       2022-06-14 17:32:39 +08:00 via iPhone
    @skinny 这里是不可能自动优化的,因为无法确保 this.value 不会被别的线程修改
    aguesuka
        15
    aguesuka  
       2022-06-15 11:20:30 +08:00   1
    你们要笑死我了, 就是个代码风格的问题, 来换个 jdk, 就不一样了.
    AbstractStringBuilder 完全不 care 性能, 因为它不是 public 的, 两个实现 StringBuilder/StringBuffer 上面有 IntrinsicCandidate 的注解. The @IntrinsicCandidate annotation is specific to the HotSpot Virtual Machine.



    private AbstractStringBuilder appendNull() {
    ensureCapacityInternal(count + 4);
    int count = this.count;
    byte[] val = this.value;
    if (isLatin1()) {
    val[count++] = 'n';
    val[count++] = 'u';
    val[count++] = 'l';
    val[count++] = 'l';
    } else {
    count = StringUTF16.putCharsAt(val, count, 'n', 'u', 'l', 'l');
    }
    this.count = count;
    return this;
    }
    ThreeK
        16
    ThreeK  
       2022-06-22 17:43:08 +08:00
    @aguesuka 你这代码不 copy 了个寂寞吗,不还是用了局部变量。
    aguesuka
        17
    aguesuka  
       2022-06-22 20:42:45 +08:00
    @ThreeK 如果效率有区别, 那么方法体里第一行应该和第二行互换, 但是没有, 说明没有区别
    ThreeK
        18
    ThreeK  
       2022-06-23 09:55:59 +08:00
    @aguesuka 这样啊,理解了,是我关注点不一样,光盯着 value 的数组了。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2467 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 28ms UTC 15:27 PVG 23:27 LAX 07:27 JFK 10:27
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86