资料内容:
简单认识这三个对象
String
String 表示的就是 Java 中的字符串,我们日常开发用到的使用 "" 双引号包围的数都是字符串的实
例。String 类其实是通过 char 数组来保存字符串的。下面是一个典型的字符串的声明
String s = "abc";
上面你创建了一个名为 abc 的字符串。
字符串是恒定的,一旦创建出来就不会被修改,怎么理解这句话?我们可以看下 String 源码的声明
告诉我你看到了什么?String 对象是由 final 修饰的,一旦使用 final 修饰的类不能被继承、方法不能
被重写、属性不能被修改。而且 String 不只只有类是 final 的,它其中的方法也是由 final 修饰的,换句
话说,Sring 类就是一个典型的 Immutable 类。也由于 String �的不可变性,类似字符串拼接、字符串
截取等操作都会产生新的 String 对象。
所以请你告诉我下面
String s1 = "aaa";
String s2 = "bbb" + "ccc";
String s3 = s1 + "bbb";
String s4 = new String("aaa");
分别创建了几个对象?
首先第一个问题,s1 创建了几个对象。字符串在创建对象时,会在常量池中看有没有 aaa 这个字
符串;如果没有此时还会在常量池中创建一个;如果有则不创建。我们默认是没有的情况,所以会
创建一个对象。下同。
那么 s2 创建了几个对象呢?是两个对象还是一个对象?我们可以使用 javap -c 看一下反汇编代
码
public class com.sendmessage.api.StringDemo {
public com.sendmessage.api.StringDemo();
Code:
0: aload_0
1: invokespecial #1 // 执行对象的初始化方法
4: return
public static void main(java.lang.String[]);
Code:
0: ldc #2 // 将 String aaa 执行入栈操作
2: astore_1
3: ldc #3 // String bbbccc
5: astore_2
6: return
}
编译器做了优化 String s2 = "bbb" + "ccc" 会直接被优化为 bbbccc 。也就是直接创建了一个 bbbccc
对象。
javap 是 jdk 自带的 反汇编 工具。它的作用就是根据 class 字节码文件,反汇编出当前类对应的
code 区(汇编指令)、本地变量表、异常表和代码行偏移量映射表、常量池等等信息。
javap -c 就是对代码进行反汇编操作。
下面来看 s3,s3 创建了几个对象呢?是一个还是两个?还是有其他选项?我们使用 javap -c 来看
一下
我们可以看到,s3 执行 + 操作会创建一个 StringBuilder 对象然后执行初始化。执行 + 号相当于是执
行 new StringBuilder.append() 操作。所以
String s3 = s1 + "bbb";
==
String s3 = new StringBuilder().append(s1).append("bbb").toString();
// Stringbuilder.toString() 方法也会创建一个 String
public String toString() {
// Create a copy, don't share the array
return new String(value, 0, count);
}
所以 s3 执行完成后,相当于创建了 3 个对象。
下面来看 s4 创建了几个对象,在创建这个对象时因为使用了 new 关键字,所以肯定会在堆中创建
一个对象。然后会在常量池中看有没有 aaa 这个字符串;如果没有此时还会在常量池中创建一个;
如果有则不创建。所以可能是创建一个或者两个对象,但是一定存在两个对象。
说完了 String 对象,我们再来说一下 StringBuilder 和 StringBuffer 对象