zoukankan      html  css  js  c++  java
  • String 总结

    申明:

    1. 首先String不属于8种基本数据类型,String是一个对象。 因为对象的默认值是null,所以String

    的默认值也是null;但它又是一种特殊的对象,有其它对象没有的一些特性。 

    2. new String()new String("")都是申明一个新的空字符串,是空串不是null
    3. String str="kvill"; 与 String str=new String ("kvill");的区别:

     

    在这里,我们不谈堆,也不谈栈,只先简单引入常量池这个简单的概念。 

    常量池(constant pool)指的是在编译期被确定,并被保存在已编译的.class文件中的一些数据。它包括了关于类、方法、接口等中的常量,也包括字符串常量。 
    1: 

     

    String s0="kvill"; 
    String s1="kvill"; 
    String s2="kv" + "ill"; 

    System.out.println( s0==s1 ); 
    System.out.println( s0==s2 );

    结果为: 

    true 
    true


    首先,我们要知结果为道Java会确保一个字符串常量只有一个拷贝。 


    因为例子中的s0s1中的"kvill"都是字符串常量,它们在编译期就被确定了,所以s0==s1true;而"kv"和"ill"也都是字符串常量,当一个字符串由多个字符串常量连接而成时,它自己肯定也是字符串常量,所以s2也同样在编译期就被解析为一个字符串常量,所以s2也是常量池中"kvill"的一个引用。 所以我们得出s0==s1==s2; 

    注:用new String() 创建的字符串不是常量,不能在编译期就确定,所以new String() 创建的字符串不放入常量池中,它们有自己的地址空间。在运行时创建的字符串具有独立的内存地址,所以不引用自同一String对象
    2: 

    String s0="kvill"; 
    String s1=new String("kvill"); 
    String s2="kv" + new String("ill"); 

    System.out.println( s0==s1 );
    System.out.println( s0==s2 );
    System.out.println( s1==s2 );

    结果为:

    false 
    false 
    false

     

    2s0还是常量池中"kvill"的应用,s1因为无法在编译期确定,所以是运行时创建的新对象"kvill"的引用,s2因为有后半部分new String("ill")所以也无法在编译期确定,所以也是一个新创建对象"kvill"的应用;明白了这些也就知道为何得出此结果了。 

    4、String.intern(): 
    存在于.class文件中的常量池,在运行期被JVM装载,并且可以扩充。Stringintern()方法就是扩充常量池的一个方法;当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(该对象由 equals(Object) 方法确定),则返回池中的字符串。否则,将此 String 对象添加到池中,并且返回此 String 对象的引用。

    3: 

    String s0= "kvill"; 

    String s1=new String("kvill"); 
    String s2=new String("kvill"); 

    System.out.println( s0==s1 ); 
    System.out.println( "**********" ); 

    s1.intern(); 
    s2=s2.intern(); //把常量池中"kvill"的引用赋给s2 

    System.out.println( s0==s1); 
    System.out.println( s0==s1.intern() ); 
    System.out.println( s0==s2 );


    结果为: 

    false 
    ********** 
    false //虽然执行了s1.intern(),但它的返回值没有赋给s1 
    true //说明s1.intern()返回的是常量池中"kvill"的引用 
    true


    4: 

    String s1=new String("kvill"); 
    String s2=s1.intern(); //s1 检查常量池 发现没有 就拷贝自己的字符串进去 ,s2 引用该字符串常量池的地址

    System.out.println( s1==s1.intern());

    System.out.println( s1+" "+s2 );
    System.out.println( s2==s1.intern());


    结果: 

    false 
    kvill kvill 
    true


    在这个类中我们没有声名一个"kvill"常量,所以常量池中一开始是没有"kvill"的,当我们调用s1.intern()后就在常量池中新添加了一个"kvill"常量,原来不在常量池中的"kvill"仍然存在。
    s1==s1.intern()false说明原来的"kvill"仍然存在; 
    s2现在为常量池中"kvill"的地址,所以有s2==s1.intern()true。 

    5、关于equals()==: 
    equals简单来说就是比较两字符串的Unicode序列是否相当,如果相等返回true;==是比较两字符串的地址是否相同,也就是是否是同一个字符串的引用。 对于字符串比较,一定要切记使用equals,勿用==.

     

    StringStringBufferStringBuilder区别

    1、三者在执行速度方面的比较:StringBuilder >  StringBuffer  >  String

    2、(StringBufferStringBuilder)在做字符串变动时将继续使用原来的内存空间,不会重新分配内存。而String的长度或内容一旦变动,JVM将分配新的内存空间。

     

    String <StringBufferStringBuilder)的原因

        String 字符串常量

        StringBuffer 字符串变量

        StringBuilder 字符串变量

    从上面的名字可以看到,String"字符串常量",也就是不可改变的对象。对于这句话的理解你可能会产生这样一个疑问,比如这段代码:

    String s = "abcd";
    s = s+1;
    System.out.print(s);// result : abcd1

    我们明明就是改变了String型的变量s的,为什么说是没有改变呢其实这是一种欺骗,JVM是这样解析这段代码的:首先创建对象s,赋予一个abcd,然后再创建一个新的对象s用来执行第二行代码,也就是说我们之前对象s并没有变化,所以我们说String类型是不可改变的对象了,由于这种机制,每当用String操作字符串时,实际上是在不断的创建新的对象,而原来的对象就会变为垃圾被GC回收掉,可想而知这样执行效率会有多底。

    StringBufferStringBuilder就不一样了,他们是字符串变量,是可改变的对象,每当我们用它们对字符串做操作时,实际上是在一个对象上操作的,这样就不会像String一样创建一些额外的对象进行操作了,效率自然提升。

     

    2一个特殊的例子:

    String str = "This is only a" + " simple" + " test";
    StringBuffer builder = new StringBuilder("This is only a").append(" simple").append(" test");

    你会很惊讶的发现,生成str对象的速度简直太快了,而这个时候StringBuilder居然速度上根本一点都不占优势。其实这是JVM的一个把戏,实际上:

        String str = "This is only a" + " simple" + "test";

    其实就是:

        String str = "This is only a simple test";

      所以不需要太多的时间了。但大家这里要注意的是,如果你的字符串是来自另外的String对象的话,速度就没那么快了,譬如:

        String str2 = "This is only a";

        String str3 = " simple";

        String str4 = " test";

        String str1 = str2 +str3 + str4;

        这时候JVM会规规矩矩的按照原来的方式去做。

    3StringBuilder与 StringBuffer

        StringBuilder:线程非安全的

        StringBuffer:线程安全的

    当我们在字符串缓冲去被多个线程使用是,JVM不能保证StringBuilder的操作是安全的,虽然他的速度最快,但是可以保证StringBuffer是可以正确操作的。当然大多数情况下就是我们是在单线程下进行的操作,所以大多数情况下是建议用StringBuilder而不用StringBuffer的,就是速度的原因。

     

    对于三者使用的总结: 

    1、如果要操作少量的数据 = String

       2、单线程操作字符串缓冲区 下操作大量数据 = StringBuilder

       3、多线程操作字符串缓冲区 下操作大量数据 = StringBuffer

  • 相关阅读:
    Arcgis中修改字段名方法
    题事件名称为CLR20r3
    【转】CLR20R3 程序终止的几种解决方案
    Ajax+asp.net无刷新验证用户名
    [转载]C/C++编译器cl.exe的命令选项
    [网络整理]DEBUG命令使用解析五
    [网络整理]DEBUG命令使用解析一
    [网络整理]DEBUG命令使用解析六
    [易学C#]C#3.0语言新特性
    [易学C#]C#3.0语言新特性之Lambda表达式
  • 原文地址:https://www.cnblogs.com/DswCnblog/p/2750172.html
Copyright © 2011-2022 走看看