String的一些思考

来源:互联网 发布:医生在线回答软件 编辑:程序博客网 时间:2024/06/02 04:23

我先问一个非常简单的问题:String是不是基本数据类型?

当然不是了。在我刚学习Java的时候,一直都以为String和int,float什么的一样,都是常用的基本数据类型。。


下面,根据我遇到过的面试题,来说道说道String,更加深刻的理解一下:


1.首先,String是一个final类,你点开源码就可以看到。被声明为final的类,都无法被继承。再一看,里边还有一个final类型的成员变量,这是用来实现字符串的存储的。

public final class String    implements java.io.Serializable, Comparable<String>, CharSequence {    /** The value is used for character storage. */    private final char value[];    /** Cache the hash code for the string */    private int hash; // Default to 0

因此我们可以得出一个结论:String是不可变的,只要你改变了字符串中的内容,就必然有新的对象生成。(这句话有毛病,话糙理不糙)

不信的话,你可以这样做:

String c = "123";System.out.println(c.hashCode());c = c + "4";System.out.println(c.hashCode());
你会发现,c的引用是改变了的,为什么?因为他们指向两个不同的在字符串常量池之中的引用。


2.StringPool和JavaHeap

StringPool是字符串常量池,JavaHeap是堆。

当我们这样声明一个str的时候,str的引用是指向字符串常量池中的:

String str = "exskil";

因此,如果以你又声明了一个String str2 = "exskil";的话,str和str2是指向同一个引用的,内存中只有一个"exskil"副本,此时如果你调用.hashCode()方法,会发现他们的hashcode相同。

当我们以new String()的方式的时候,str的引用是指向之中的:

String str = new String("exskil");

不过,以new String()的方式来创建一个String对象的方式,会创建两个对象(并不是同时,注意,并不是同时),一个是new出来保存在堆中的,另一个就是由""双引号创建的,只不过他们创建的时期不同。

new是在运行时创建对象的,而双引号"'是在编译期就在字符串常量池中创建对象的


3.String的intern()方法

先说一下intern()方法的作用:str.intern("exskil");调用此方法时,如果StringPool中已经有一个等于"exskil"的字符串的话,则返回池中的字符串,不然就在StringPool中创建一个"exskil"。

也就是说,和双引号""不同,intern()方法是可以在运行时在StringPool中创建新的对象的。


通过上述思考,面试题中的字符串比较问题应该可以迎刃而解了。


4.String的创建方法

看了这么多,你应该意识到了,String的创建方法有如下几种:

1.引号""编译期创建

2.new运行时创建

3.通过String重载的运算符+加号创建


5.String和StringBuffer的效率问题?

我们经常说,StringBuffer的效率比较高,因为在对字符串进行修改操作的时候,StringBuffer对象只会在自己当前对象上进行修改,而String是一个不可变类,要进行字符串的修改操作会新建对象。因此,StringBuffer的效率要高于String。

但是这里有一个误区,是一个坑,比如说对字符串进行添加操作。

StringBuffer sb = new StringBuilder("a").append("b").append("c");

String str = "a" + "b" + "c";

由于"a" + "b" + "c"是在编译期就已经创建在字符串常量池中,并不会创建新的String对象,而StringBuffer还要在运行时修改自身对象,这时候String的效率是高于StringBuffer的。

当然,在大部分情况下,StringBuffer的效率自然是要高于String的。


原创粉丝点击