JAVA 基础知识点复习(三)引用数据类型 String


这系列博文主要是将自己之前学习的一些java基础内容进行归纳与总结。

常用方法

int length() // 获取长度
char charAt(int index) // 获取对应角标的字符
int indexOf(String str) // 获取对应角标
String substring(int beginIndex, int endIndex) // 截取区间返回 包含开头不包含结尾
String[] split(String regex, int limit) // 根据正则表达式分隔字符,limit应用次数
String trim() // 忽略前后空白
String replace(char oldChar, char newChar) // 替换
char[] toCharArray() // 分解成字符数组
String intern()  // 判断常量池是否存在该字符串,如果存在则返回,否则在常量池记录首次出现的引用(jdk1.7后)

Sting对equals方法的重写

// Object的equals方法 直接通过==比较内存地址
    public boolean equals(Object obj) {
        return (this == obj);
    }

// String对equals方法进行了重写 先比较内存地址如果不相等再比较字符串值是否相同
public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            .... // 逐个char进行比较
        }
}

String的比较

String s1 = new String("aaa");
String s2 = "aaa";
System.out.println(s1 == s2); // false

s1 = new String("bbb").intern();
s2 = "bbb";
System.out.println(s1 == s2); // true

s1 = "ccc";
s2 = "ccc";
System.out.println(s1 == s2); // true

s1 = new String("ddd").intern();
s2 = new String("ddd").intern();
System.out.println(s1 == s2); // true

s1 = "ab" + "cd";
s2 = "abcd";    
System.out.println(s1 == s2); // true

String temp = "hh";
s1 = "a" + temp;
// 如果调用s1.intern 则最终返回true
s2 = "ahh";
System.out.println(s1 == s2); // false

temp = "hh".intern();
s1 = "a" + temp;
s2 = "ahh";
System.out.println(s1 == s2); // false

temp = "hh".intern();
s1 = ("a" + temp).intern();
s2 = "ahh";
System.out.println(s1 == s2); // true

s1 = new String("1"); // 同时会生成堆中的String对象 以及常量池中的"1",但是此时s1是指向堆内存的String对象
s1.intern(); // 返回的是常量池中的已经存在"1"的引用
s2 = "1"; // 还是指向常量池中已存在的"1"
System.out.println(s1 == s2);    // false

// 先调用intern
String s3 = new String("1") + new String("1"); // 此时生成了四个对象 常量池中的"1" + 2个堆中的"1" + s3指向的堆中的对象(注此时常量池不会生成"11")
s3.intern();    // jdk1.7之后,常量池不仅仅可以存储对象,还可以存储对象的引用,会直接将s3的地址存储在常量池
String s4 = "11";    // jdk1.7之后,常量池中的地址其实就是s3的地址
System.out.println(s3 == s4); // jdk1.7之前false, jdk1.7之后true

// 后调用intern
s3 = new String("2") + new String("2");
s4 = "22";        // 常量池中不存在22,所以会新开辟一个存储22对象的常量池地址
s3.intern();    // 常量池22的地址和s3的地址不同,若 s3 = s3.intern() 则为true
System.out.println(s3 == s4); // false

String在内存中的对象创建

  • 字符串相加如果没有任何变量参与,则编译器对String做了优化,会直接拼接转化为一个字符串
  • 若有变量参与则是通过new StringBuild().append()相加
  • new String(“E”) + new String(“F”) 一共创建了五个变量
String s1 = "A" + "B" + "C"; // 直接在常量池中创建 "ABC"
// 字节码:
    Code:
       0: ldc           #2                  // String ABC
       2: astore_1
       3: return
           
String s2 = s1 + "D"; // 在堆中new StringBuilder,通过append相加
// 字节码:
    Code:
       0: ldc           #2                  // String ABC
       2: astore_1
       3: new           #3                  // class java/lang/StringBuilder
       6: dup
       7: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V
      10: aload_1
      11: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      14: ldc           #6                  // String D
      16: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      19: invokevirtual #7                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      22: astore_2
      23: return
    
String s3 = new String("E") + new String("F"); // 创建了五个对象, 常量池中的"E"、"F",堆中的"E"、"F",s3指向堆中的对象
// 字节码:
    Code:
       0: new           #2                  // class java/lang/StringBuilder
       3: dup
       4: invokespecial #3                  // Method java/lang/StringBuilder."<init>":()V
       7: new           #4                  // class java/lang/String
      10: dup
      11: ldc           #5                  // String E
      13: invokespecial #6                  // Method java/lang/String."<init>":(Ljava/lang/String;)V
      16: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      19: new           #4                  // class java/lang/String
      22: dup
      23: ldc           #8                  // String F
      25: invokespecial #6                  // Method java/lang/String."<init>":(Ljava/lang/String;)V
      28: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      31: invokevirtual #9                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      34: astore_1
      35: return

IDEA中在控制台打印执行的字节码

在Setting中配置External Tools

在这里插入图片描述参数说明

Name: Show Byte Code (随意)
Program: C:\Program Files\Java\jdk1.8.0_144\bin\javap.exe (jdk bin目录下的javap.exe)
Arguments: -c $FileClass$ (照填)
Working directory: $OutputPath$ (照填)

然后右键执行即可

在这里插入图片描述

原创文章 7 获赞 0 访问量 6220

猜你喜欢

转载自blog.csdn.net/weixin_42598683/article/details/105255261