字符串是最常用的数据类型,甚至比基本类型还用的多。正因如此,java 也对String 做了一些特殊处理,使得我们在编程时使用String 和 使用自动装箱的基本数据类型包装类很相似。
如:
包装类: Integer a = 1; a =a+1;
String: String a ="abc"; a=a+"d";
但不要因此就认为String 也是使用自动装箱技术。请看:
代码 1
String as = "abc";
String bs = new String("abc");
System.out.println(as == bs);
System.out.println(as.equals(bs));
int b = 1;
Integer a = new Integer(1);
System.out.println(a == b);
System.out.println(a.equals(b));
上面代码结果: false true true true
结果很明显,虽然String 用法很接近自动装箱的包装类,但也仅仅是用法相似而已,本质是不同的。那么String 本质是什么呢?
也是个包装类,但包装的不是基本类型,而是字符数组 char[],记住在java 中数组也是对象,所以说是包装的另一个对象。因为String 太常用。java 在底层给其多赋予了一种创建方式,也就是利用双引号对直接创建,如 "abc" 就是创建了一个String 对象。至于创建到内存哪了,后文会分析,现在先回去看下代码 1 中第二句,很和熟悉吧,参加过面试的程序猿们更熟悉。都知道创建了两个对象,一个“abc",另一个还是”abc"。两个一样不是浪费吗,所以大家们不推荐用这种方式创建。这两个对象有什么区别呢,可以告诉你一个你可能已经知道的答案,即放的内存位置不同,但并不是很多面试答案中说的一个堆,一个在栈,具体也后面再说。这里先解决为什么创建了两个对象。
其实上面也已经说String太常用java 在底层给它添加了一种创建方法,而new 是我们常见的创建方法。所以那句是用引号方式创建了一个对象,又用new 方式再创建了一个。从String 源代码来看就更清晰了。
代码 2
// ...
public String(String original) {
int size = original.count;
char[] originalValue = original.value;
char[] v;
if (originalValue.length > size) {
// The array representing the String is bigger than the new
// String itself. Perhaps this constructor is being called
// in order to trim the baggage, so make a copy of the array.
int off = original.offset;
v = Arrays.copyOfRange(originalValue, off, off+size);
} else {
// The array representing the String is the same
// size as the String, so no point in making a copy.
v = originalValue;
}
this.offset = 0;
this.count = size;
this.value = v;
}
从上面源代码可以看出,new 新建的String对象,‘拷贝’了 original 对象的数据。
下面将从两种创建对象方式着手分析他们的异同。
12