java基础--特殊的String
有个问题,在网上十分常见,就是这样一段代码
有人往往会问:他创建了几个对象?我想答案是众所周知的2个。这个问题也从一个侧面说出了String的一些不同。
我们接着说创建String对象的另-中方式:
显然,这种方式他创建了一个对象。这种方式是String特有的(确实我们在java中好像没有看到过也从来没有过其他对象这样的方式创建)。其实java中这样设置String,应该是让他和内置的基本类型定义时一致。
然后我们再来看看这样一段代码:
String str2="hya";
他创建的对象还是一个,以前初学时我就感到疑惑。为什么会是一个呢?
其实java里有一个字符串池的概念。确切地应该说是jvm中存在着一个字符串池,其中保存着很多String对象,并且可以被共享使用,因此它提高了效率。由于String类是final的,它的值一经创建就不可改变,因此我们不用担心String对象共享而带来程序的混乱。字符串池由String类维护,我们可以调用intern()方法来访问字符串池。 (来自javaeye的定义)
当我们遇到String str1=“hya”的语句时,Java会先在字符串池中寻找是否已经存在"hya"这个字符串,如果没有,则建立字符串"hya"对象,然后变量 str1指向这个地址;然后遇到语句String str2=“hya”这时字符串池中已经有 "hya"了,所以直接让变量str2也指向这个地址。
我们再来看看String str=new String("a");这个语句如何处理的呢?"a"是字符串池中的一个对象,然后new String()是建立一个对象,并将句柄赋值给str,这与其他的对象建立没有什么不同。
以让的知识介绍完后,我们再来看看这个问题(考试哦!)
String s=new String("a");
他创建了几个对象?如果明白了上面的知识的话,这个答案是不容置疑的!!!
然后我们再来看看,实际编程中遇到的==和equqls的区别,这里主要针对String而言的。
看如下代码:
String b = "Hello";
String c = new String("Hello");
String d = new String("Hello");
System.out.println(a == b);
System.out.println(b == c);
System.out.println(c == d);
System.out.println(a.equals(b));
System.out.println(b.equals(c));
System.out.println(c.equals(d));
输出结果是
false
false
true
true
true
呵呵,看出什么了吗?首先我们来说明一下在java中==和equqls的区别:
==:对于基本类型来说是则是判断它们的值是否相等;对于两个对象则是判断它们的引用是否指向同一个对象;
equqls:是一个方法,针对基本类型的外覆盖类和String而言它是判断值是否相等;而对于普通的对象,他们的缺省的实现和==并没有区别。
所以对于上面的一段代码,不管他们是不是同一个对象,他们的值都是Hello,所以用equqls方法,返回的值都是true。
由于java中String的用处十分的广,所以初于使用和性能上的考虑,对他作了一些特殊处理。最后我们再来说说String对象在JVM中的存储,以及字符串池与heap和stacK的关系。java中的数据主要存储在heap和stacK这两个数据结构中其中:栈(stack):主要保存基本类型(或者叫内置类型)(char、byte、short、int、long、float、double、boolean)和对象的引用,数据可以共享,速度仅次于寄存器(register),快于堆。 堆(heap):用于存储对象。
我们查看String类的源码就会发现,它有一个value属性,保存着String对象的值,类型是char[],这也正说明了字符串就是字符的序列。
当执行String a="hya";时,JVM会在栈中创建三个char型的值'h'、'y'和'a',然后在堆中创建一个String对象,它的值(value)是刚才在栈中创建的三个char型值组成的数组{'h','y','a'},最后这个新创建的String对象会被添加到字符串池中。如果我们接着执行String b=new String("hya");代码,由于"hya"已经被创建并保存于字符串池中,因此JVM只会在堆中新创建一个String对象,但是它的值(value)是共享前一行代码执行时在栈中创建的三个char型值值'a'、'b'和'c'。
ps:以上属于个人理解,如有错误,还请指正!谢谢!