Java源码阅读--String

String

方法解释

indexOf

此方法没有使用KMP算法,而是直接进行暴力匹配,理由可能是因为程序中大多数的字符串比较短,而KMP算法需要初始化计算以及分配内存故而在较短的字符串中使用暴力效率更高。

intern

如果字符串常量池中包含次字符串,则返回此字符串的引用,否则 将此字符串添加到字符串常量池池中并返回其在常量池中的引用

String b = new String("abc");
System.out.println(b.intern()==b);//false

并且需要注意的是使用new创建的字符串对象并不会进入字符串常量池中,使用静态方法创建的则会进入字符串常量池中如:

String a="abc";
String c = new String("abc");
System.out.println(a==c);//false
System.out.println(a.intern()==a);//true

使用静态方法创建字符串时,首先会在字符串常量池中查找是否有此字符串,如果equals比较相等则存在返回此字符串的常量池地址,不存在则添加此字符串到常量池中并返回其地址:

String a="abc";
String b="abc";
System.out.println(a==b);//true

注释解释

在源码注释中存在着这么语句注释

/* avoid getfield opcode */

其意思是避免使用getfield操作码。

对下面这段代码进行反编译:

public class Main{
    char[] chars=new char[10];

    int tt(){
        char c1=chars[0];
        char c2=chars[1];
        char c3=chars[2];
        return c1 + c2 + c3;
    }
}

其中tt()方法为:

int tt();
    Code:
       0: aload_0
       1: getfield      #2                  // Field chars:[C
       4: iconst_0
       5: caload
       6: istore_1
       7: aload_0
       8: getfield      #2                  // Field chars:[C
      11: iconst_1
      12: caload
      13: istore_2
      14: aload_0
      15: getfield      #2                  // Field chars:[C
      18: iconst_2
      19: caload
      20: istore_3
      21: iload_1
      22: iload_2
      23: iadd
      24: iload_3
      25: iadd
      26: ireturn
  • 0:获取this
  • 1:获取指定类的实例域,并将其值压入栈顶
  • 4:将 int 型 0 推送至栈顶
  • 5:将 char 型数组指定索引的值推送至栈顶
  • 6:将栈顶 int 型数值存入第二个本地变量(从0开始计数)

tt()方法中每一次访问chars数组的值,都会重复上面的五个步骤,再对下面这段代码进行反编译:

public class Main{
    char[] chars=new char[10];

    int tt2(){
        char[] chars = this.chars;/* avoid getfield opcode */
        char c1=chars[0];
        char c2=chars[1];
        char c3=chars[2];
        return c1 + c2 + c3;
    }
}

其中tt2()方法为:

 int tt2();
    Code:
       0: aload_0
       1: getfield      #2                  // Field chars:[C
       4: astore_1
       5: aload_1
       6: iconst_0
       7: caload
       8: istore_2
       9: aload_1
      10: iconst_1
      11: caload
      12: istore_3
      13: aload_1
      14: iconst_2
      15: caload
      16: istore        4
      18: iload_2
      19: iload_3
      20: iadd
      21: iload         4
      23: iadd
      24: ireturn

其中0、1、4为char[] chars = this.chars;此时已经将chars引用保存到astore_1(方法栈的第二个本地变量)中了,接下来的每次访问chars的数值就不再需要使用getfield操作码获取类的实例域类,而是直使用aload_1从方法栈的本地变量中获取类减少了getfield操作

posted @ 2022-02-09 10:13  TKG  阅读(44)  评论(0)    收藏  举报