`
tianke66
  • 浏览: 188067 次
  • 性别: Icon_minigender_1
  • 来自: 西安
文章分类
社区版块
存档分类
最新评论

string 2

阅读更多

要理解 java中String的运作方式,必须明确一点:String是一个非可变类(immutable)。什么是非可变类呢?简单说来,非可变类的实例是不能被修改的,每个实例中包含的信息都必须在该实例创建的时候就提供出来,并且在对象的整个生存周期内固定不变。java为什么要把String设计为非可变类呢?你可以问问 james Gosling :)。但是非可变类确实有着自身的优势,如状态单一,对象简单,便于维护。其次,该类对象对象本质上是线程安全的,不要求同步。此外用户可以共享非可变对象,甚至可以共享它们的内部信息。(详见 《Effective java》item 13)。String类在java中被大量运用,甚至在class文件中都有其身影,因此将其设计为简单轻便的非可变类是比较合适的。
一、创建。
    好了,知道String是非可变类以后,我们可以进一步了解String的构造方式了。创建一个Stirng对象,主要就有以下两种方式:


java 代码
String str1 = new String("abc");    
Stirng str2 = "abc";  

     虽然两个语句都是返回一个String对象的引用,但是jvm对两者的处理方式是不一样的。对于第一种,jvm会马上在heap(堆)中创建一个String对象,然后将该对象的引用返回给用户。对于第二种,jvm首先会在内部维护的strings pool(池)中通过String的 equels 方法查找是对象池中是否存放有该String对象,如果有,则返回已有的String对象给用户,而不会在heap中重新创建一个新的String对象;如果对象池中没有该String对象,jvm则在heap中创建新的String对象,将其引用返回给用户,同时将该引用添加至strings pool中。注意:使用第一种方法创建对象时,jvm是不会主动把该对象放到strings pool里面的,除非程序调用 String的intern方法。看下面的例子:

        String str1 = new String("abc"); //jvm 在堆上创建一个String对象    
           
         
//jvm 在strings pool中找不到值为“abc”的字符串,因此    
         
//在堆上创建一个String对象,并将该对象的引用加入至strings pool中    
         
//此时堆上有两个String对象    
        String str2 = "abc";    
           
         
if(str1 == str2)...{    
                 System.out.println(
"str1 == str2");    
         }
else...{    
                 System.out.println(
"str1 != str2");    
         }
    
          
//打印结果是 str1 != str2,因为它们是堆上两个不同的对象    
           
          String str3 
= "abc";    
         
//此时,jvm发现strings pool中已有“abc”对象了,因为“abc”equels “abc”    
         
//因此直接返回str2指向的对象给str3,也就是说str2和str3是指向同一个对象的引用    
          if(str2 == str3)...{    
                 System.out.println(
"str2 == str3");    
          }
else...{    
                 System.out.println(
"str2 != str3");    
          }
    
         
//打印结果为 str2 == str3  

再看下面的例子:

        String str1 = new String("abc"); //jvm 在堆上创建一个String对象    
           
        str1 
= str1.intern();    
//        程序显式将str1放到strings pool中,intern运行过程是这样的:首先查看strings pool    
//        有没“abc”对象的引用,没有,则在堆中新建一个对象,然后将新对象的引用加入至    
//        strings pool中。执行完该语句后,str1原来指向的String对象已经成为垃圾对象了,随时会    
//        被GC收集。    
           
//        此时,jvm发现strings pool中已有“abc”对象了,因为“abc”equels “abc”    
//        因此直接返回str1指向的对象给str2,也就是说str2和str1引用着同一个对象,    
//        此时,堆上的有效对象只有一个。    
        String str2 = "abc";    
           
         
if(str1 == str2)...{    
                 System.out.println(
"str1 == str2");    
         }
else...{    
                 System.out.println(
"str1 != str2");    
         }
    
          
//打印结果是 str1 == str2  

为什么jvm可以这样处理String对象呢?就是因为String的非可变性。既然所引用的对象一旦创建就永不更改,那么多个引用共用一个对象时互不影响。

二、串接(Concatenation)。
     java程序员应该都知道滥用String的串接操作符是会影响程序的性能的。性能问题从何而来呢?归根结底就是String类的非可变性。既然String对象都是非可变的,也就是对象一旦创建了就不能够改变其内在状态了,但是串接操作明显是要增长字符串的,也就是要改变String的内部状态,两者出现了矛盾。怎么办呢?要维护String的非可变性,只好在串接完成后新建一个String 对象来表示新产生的字符串了。也就是说,每一次执行串接操作都会导致新对象的产生,如果串接操作执行很频繁,就会导致大量对象的创建,性能问题也就随之而来了。
    为了解决这个问题,jdk为String类提供了一个可变的配套类,StringBuffer。使用StringBuffer对象,由于该类是可变的,串接时仅仅时改变了内部数据结构,而不会创建新的对象,因此性能上有很大的提高。针对单线程,jdk 5.0还提供了StringBuilder类,在单线程环境下,由于不用考虑同步问题,使用该类使性能得到进一步的提高。

三、String的长度
   我们可以使用串接操作符得到一个长度更长的字符串,那么,String对象最多能容纳多少字符呢?查看String的源代码我们可以得知类String中是使用域 count 来记录对象字符的数量,而count 的类型为 int,因此,我们可以推测最长的长度为 2^32,也就是4G。
    不过,我们在编写源代码的时候,如果使用 Sting str = "aaaa";的形式定义一个字符串,那么双引号里面的ASCII字符最多只能有 65534 个。为什么呢?因为在class文件的规范中, CONSTANT_Utf8_info表中使用一个16位的无符号整数来记录字符串的长度的,最多能表示 65536个字节,而java class 文件是使用一种变体UTF-8格式来存放字符的,null值使用两个字节来表示,因此只剩下 65536- 2 = 65534个字节。也正是变体UTF-8的原因,如果字符串中含有中文等非ASCII字符,那么双引号中字符的数量会更少(一个中文字符占用三个字节)。如果超出这个数量,在编译的时候编译器会报错。

分享到:
评论

相关推荐

    分支与循环程序设计 将一个包含20个元素的数组STRING分成一个偶数数组STRING1和一个奇数数组STRING2

    在本实验中,我们将学习如何使用条件转移指令、串操作指令和循环指令来编写一个将一个包含20个元素的数组STRING分成一个偶数数组STRING1和一个奇数数组STRING2的程序。 二、实验要求 1. 掌握条件转移指令的使用...

    String对象创建问题

    在Java编程语言中,`String`对象的创建是开发者经常遇到的问题,因为它涉及到内存管理和效率。`String`类在Java中被广泛使用,因为它代表不可变的字符序列,这使得它在很多场景下非常安全。这里我们将深入探讨`...

    java String 使用详解

    2. compareTo 方法 compareTo 方法的作用是比较两个字符串的大小,比较的原理是依次比较每个字符的字符编码。首先比较两个字符串的第一个字符,如果第一个字符串的字符编码大于第二个的字符串的字符编码,则返回...

    stl string常用函数

    STL String 类常用函数 STL String 类是一个基本的字符串类,提供了多种构造函数、字符操作、输入输出操作、赋值操作、连接操作和比较操作等功能。 构造函数 STL String 类提供了多种构造函数,可以根据不同的...

    string、wstring、cstring、 char、 tchar、int、dword转换方法

    void ConvertCString2string(CString& strSrc, std::string& strDes) { #ifndef UNICODE strDes = strSrc; #else #uses_conversion; strDes = W2A(strSrc.LockBuffer()); strSrc.UnlockBuffer(); #endif } ``` ...

    string对象的操作pdf

    - **从中间位置赋值**:`s.assign(str, 2, std::string::npos);` 从索引 2 开始复制直到字符串结束。 - **重复字符赋值**:`s.assign(5, 't');` ##### 2.2 常用操作方法 - **empty()**:判断字符串是否为空。 - **...

    Android byte[] 和 String互相转换

    在提供的`String2Byte`项目中,可能包含了上述转换方法的简单示例代码,供开发者学习和参考。通过实际运行和调试这些代码,可以更深入地理解`byte[]`与`String`之间的转换过程。 综上所述,理解和熟练掌握`byte[]`...

    CString和string对象

    2. CString和int之间的转化 CString也可以与int类型之间进行转化。例如,我们可以使用CString的format函数来将int类型转化为CString。 int i = 123; CString str; str.Format("%d", i); // int -> CString i = ...

    Java常用类与基础API-String的构造器与常用方法

    ##### (2)String与其他结构间的转换 1. **基本数据类型、包装类 --> 字符串**: - 可以通过 `String.valueOf()` 方法或者 `+` 运算符来实现转换。 - 示例代码: ```java int num = 100; String s = String....

    C++ string类常用函数

    C++ string 类常用函数 C++ 中的 string 类是一个非常常用的类,它提供了很多有用的函数来操作字符串。下面对 string 类的常用函数进行详细的介绍。 构造函数 C++ 中的 string 类有多种构造函数,可以用不同的...

    StringBuffer和String_区别

    ### StringBuffer与String的区别详解 #### 一、概念与特性 **String** 是 Java 中一个不可变的类,代表了字符序列。一旦一个 String 对象被创建后,其内容就不能被改变。这使得 String 类非常适合用来表示常量或者...

    C++string类常用函数

    ### C++ `string` 类常用函数详解 #### string 类的构造函数 `string` 类提供了多种构造函数,以便用户能够灵活地创建 `string` 对象。 - **使用 C 风格字符串初始化**:`string(const char *s);` - 这种构造...

    正确使用String类的几点注意

    ### 正确使用String类的几点注意 在Java编程中,`java.lang.String`类是极为常见的基础数据类型之一,其重要性和应用范围不言而喻。为了更好地理解和使用String类,本文将从几个关键方面入手,探讨如何更加高效、...

    12基础篇之第十二(String的基本用法).docx

    2. **字节数组构造**:`String(byte[] bytes)` 和 `String(byte[] bytes, int index, int length)` 分别用于将整个字节数组或部分字节数组转换为字符串。 3. **字符数组构造**:`String(char[] value)` 和 `String...

    JAVA_String

    2. 使用`new`关键字和构造函数,如`String str = new String("Hello, World!");` 3. 字符数组转换,如`char[] chars = {'H', 'e', 'l', 'l', 'o'}; String str = new String(chars);` `String`类提供了丰富的操作...

    IBM-PC汇编 程序设计 Sample.asm 比较字符串

    IBM-PC汇编程序设计语言 1.2 实验方法, 比较两个字符串string1和string2所含的字符是否相同。若相依则显示'Match',否则,显示'No match'

    Java中颜色的String和Color对象之间的互相转换

    public static Color String2Color(String str) { int i = Integer.parseInt(str.substring(1), 16); return new Color(i); } ``` 在上面的代码中,我们首先将字符串从第二个字符开始截取,直到字符串结尾,然后将...

Global site tag (gtag.js) - Google Analytics