在任何编程语言中,字符串都是我们编写程序时不可避免要用到的常用的数据类型之一. 对于Java初学者而言,当谈到String和StringBuffer的区别时,通常都会有些困惑. 而要弄清楚两者之间的区别,正确地理解String类是最为关键的.

1. java.lang.String is immutable

在Java中string是一个对象,String类位于java.lang包中,在Java中String对象中的每一个字符(character)都是16bit的Unicode字符.

创建一个String对象的方法有如下3种:

1.  String s = new String();

s = “abcdef”;

2.String s = new String(“abcdef”);

3.String s = “abcdef”;

上面三种方法的结果是:创建了一个String对象,其值为“abcdef”,将其赋给一个reference variable s.

String is immutable, but it reference is not.

而关于java.lang.String我们要理解的关键一点是:一个String对象一旦被创建,就不允许被改变(Once a String object is created, it can never be created.). 或者我们说,这被称为String objects的immutability,即:一旦赋一个值给String对象,该值就不能够再被改变,这个值是immutable的.

我们要明白的关键是,说String对象是不可变的,是指其值是不可变的,但是该对象的引用变量是可变的,可以将其改变指向任何其他String对象实例(While the String object is immutable, its reference variable is not.). 例如:

String a = “abcedf”;

a2 = a;

a = a.concat(“ more staff”);

上述这个很简单的例子可描述如下:String is immutable.故a的值不能够改变,所以a.concat(“ more staff”)生成了一个新的String:“abcdef more staff”,将String Object reference a重新指向这个新的String Object—“abcdef more staff”。也就是说,迄今为止,一共有三个String Object生成:“abcdef”,“ more staff”以及“abcdef more staff”

必须牢记的是:表面上看到的String的改变,实际上是其reference的改变. 这就体现了String对象的Immutability.

2. Java中关于String的内存管理的特殊性

任何好的编程语言的主要目标之一就是要能够高效地使用宝贵的内存资源.

而在Java中为了高效地使用我们最常用的数据类型:字符串. JVM专门在内存中设定了一个特殊的区域:字符串常量池/String Constant Pool. 当编译器遇到一个字符串字面值/String Leteral,它首先检查字符串常量池/String Constant Pool. 如果池中存在同样的一个字符串,那么编译器就不会再创建新的字符串对象,而是会将一个字符串的引用指向该匹配的字符串对象.

这样,JVM可以保证对于java程序中的字符串字面值/String Literal以较为高效的方式来使用.

但是,我们也应该会注意到,在这种情况下,可能会有多个字符串对象的引用变量指向字符串常量池/String Constant Pool中的同一个字符串对象. 而同时,如果每个指向该对象的引用都对该对象(的值)不加限制的进行改变,就会出现混乱. 所以,在Java中,将String类设置为final的原因之一就是为了保证其immutability特性—没有人可以override String的方法.

特别注意:对于String对象的不当使用,可能会产生许多被丢弃在String Constant Pool中的字符串常量. 会浪费宝贵的内存资源.

3. 哪些String对象可以进入String Constant Pool/字符串常量池

我们需要明确的是:在Java中,JVM只对于String Literal Object才进行池化(把它们放入特殊的内存区域—String Constant Pool)—中.  参看下面的两个例子:

1. String s = "abc";   //创建了一个String对象和一个String类型的reference变量

在这个简单的例子中, “abc”将会被JVM放进String Constant Pool,同时,String类型的reference变量s会指向它

2. String s = new String("abc");  //创建了两个String对象和一个String类型的reference变量

在这个例子中,由于我们使用了new关键字,JVM会创建两个String对象,一个是与例1中相同的String literal Object “abc”,它会被放入到String Constant Poll中去. 而另为一个则使用new关键字创建的普通的Java String对象,它会被放到Java程序所使用的普通得内存区域中去(normal (non-pool) memory).

从上面的叙述可以看到:只有使用“”(没有使用new)直接创建的String literal才可以被放在String constant pool中.

4.常用的String方法

Ø         public char charAt(int index)

获得字符串中指定索引处的字符(注意:字符串的索引是从0开始的/String indexes are zero-based

Ø         public String concat(String s)

连接生成一个新的字符串对象,该字符串的值 = 调用者的值 + 做为参数的字符串的值. 例如:

String x = "library";

System.out.println( x + " card"); // output is "library card"

Ø         public boolean equalsIgnoreCase(String s)

比较调用者与参数字符串对象的值在不区分大小写的情况下是否相等

Ø         public int length()

返回字符串的长度/字符数. 注意与Array对象的属性length区别:String是length()方法/成员函数;Array是length属性/成员变量.

Ø         public String replace(char old, char new)

生成发生字符替换后的新字符串. 注意:会替换所有遇到的旧字符.

Ø         public String substring(int begin)

返回从参数所指位置—>原字符串结尾处的字串

Ø         public String substring(int begin, int end)

返回从参数所指位置之间的字串.

需要注意的是:开始位置的index是zero-based,但是结束位置的则不是. 注意下面例子:

String x = "0123456789";

System.out.println( x.substring(5) ); // output is "56789"

System.out.println( x.substring(5, 8)); // output is "567"

Ø         public String toLowerCase()

生成新的全部字符转换为小写的字符串

Ø         public String toUpperCase()

生成新的全部字符转换为大写的字符串

Ø         public String trim()

生成新的去掉首位空格的字符串

5. StringBuffer

StringBuffer objects are changeable

StringBuffer对象是可变的,故使用它不会产生很多discard String literal在String constant pool中,相比较String而言,它的效率更高一些.

而且,StringBuffer的许多方法是线程安全的.

6. StrngBuffer的常用方法

Ø         public synchronized StringBuffer append(String s)

将参数所示的字符串连接在原StringBuffer所代表的String的末尾。

与String的concat(String)方法不同StringBuffer的append(String)方法不会产生新的对象,只是改变来原对象的值.

Ø         public synchronized StringBuffer insert(int offset, String s)

从offset位置开始插入字符串s,其中offset是zero-based的

Ø         public synchronized StringBuffer reverse()

反转StringBuffer对象多代表的字符串,例如:

StringBuffer sb = new StringBuffer("A man a plan a canal Panama");

System.out.println( sb );      //output is“amanaP lanac a nalp a nam A”

Ø         public String toString()

返回StringBuffer对象所代表的String的值,例如:

StringBuffer sb = new StringBuffer("test string");

System.out.println( sb.toString() ); // output is "test string"

Java中的String和StringBuffer的更多相关文章

  1. Java中的String、StringBuffer和StringBuilder

    作为作为一个已经入了门的java程序猿,肯定对Java中的String.StringBuffer和StringBuilder都略有耳闻了,尤其是String 肯定是经常用的.但肯定你有一点很好奇,为什 ...

  2. 浅谈java中的String、StringBuffer、StringBuilder类的区别以及关系

    在java中最常见的使用就是对字符串的操作:首先先说一下对字符串的理解:字符串就是一连串字符序列,Java提供了String和StringBuffer两个类来封装字符串,并提供一系列方法来操作字符串对 ...

  3. Java中的String、StringBuffer以及StringBuilder的用法和区别

    String String的构造方式有n种(据说n==11),常见的例举一二: String s1 = "hello world"; String s2 = new String( ...

  4. Java中的String,StringBuffer,StringBuilder详解与区别

    1.String Java中string类是不可变的,其中在声明的源代码中用的final,所以只能声明一次.所以每次在明面上的改变其实是重新生成一个String对象,指针指向新的String对象.同时 ...

  5. Java中的String、StringBuffer和StringBuilder的区别

    类型  是否可变  线程安全  能否频繁修改  String  不可变  安全  否  StringBuffer  可变  安全  能  StringBuilder  可变  不安全  能 1.可变与 ...

  6. 深刻理解Java中的String、StringBuffer和StringBuilder的差别

    声明:本博客为原创博客,未经同意.不得转载!小伙伴们假设是在别的地方看到的话,建议还是来csdn上看吧(链接为http://blog.csdn.net/bettarwang/article/detai ...

  7. java中的String、StringBuffer、StringBuilder的区别

    java中String.StringBuffer.StringBuilder是编程中经常使用的字符串类,他们之间的区别也是经常在面试中会问到的问题.现在总结一下,看看他们的不同与相同. 1.可变与不可 ...

  8. Java中的String、StringBuffer、StringBuilder区别以及Java之StringUtils的用法

    1.String.StringBuffer.StringBuilder的区别 String是Java中基础类型,是immutable类(不可变)的典型实现,利用string进行拼接是会产生过多无用对象 ...

  9. Java中的String,StringBuffer和StringBuilder

    在了解这个问题的时候查了不少资料,最有帮助的是这个博文:http://swiftlet.net/archives/1694,看了一段时间,咀嚼了一段时间,写一个经过自己消化的博文,希望能帮到大家. 首 ...

随机推荐

  1. 使用SSH工具连接到MySQL

    在SSH中查看MySQL数据信息 格式为:mysql -h主机地址 -u用户名 -p用户密码 -P端口号 -D数据库名称 例如: mysql -uroot -p123456 -h192.168.1.1 ...

  2. PHP获取目录和的方法通过魔术变量;通过超级全局变量;通过相关函数等等:

    <?php /** * PHP获取路径或目录实现 * @link http://www.phpddt.com */ //魔术变量,获取当前文件的绝对路径 echo "__FILE__: ...

  3. 您好,python的请求es的http库是urllib3, 一个请求到贵司的es节点,想了解下,中间有哪些网关啊?冒昧推测,贵司的部分公共网关与python-urllib3的对接存在异常?

    您好,python的请求es的http库是urllib3, 一个请求到贵司的es节点,想了解下,中间有哪些网关啊?冒昧推测,贵司的部分公共网关与python-urllib3的对接存在异常? 负载均衡( ...

  4. 洛谷P5151 HKE与他的小朋友 快速幂/图论+倍增

    正解:矩阵快速幂/tarjan+倍增 解题报告: 传送门! 跟着神仙做神仙题系列III 这题首先一看到就会想到快速幂趴?就会jio得,哦也不是很难哦 然而,看下数据范围,,,1×105,,,显然开不下 ...

  5. 【调研与分析】标杆学习、知识管理和竞争情报的关系——From Team

    注: 1)红色实线箭头表示可以直接使用:例如竞争情报业务输出产品之一的标杆文档可以直接作为公司标杆学习中外部标杆的资料: 2)蓝色虚线箭头表示转化后使用或者间接利用的关系:例如专题调研可以帮助建立内部 ...

  6. sql server 用脚本管理作业

    转自:https://blog.csdn.net/yunye114105/article/details/6594826 摘要: 在SQL SERVER中用脚本管理作业,在绝大部分场景下,脚本都比UI ...

  7. ViewPager添加小圆点

    ViewPager添加小圆点很简单,但是如果是网络图片可能就不太好做了,所以我这里给出一种方法,当然你也可以用其他的 1.主界面xml <?xml version="1.0" ...

  8. Flask系列(二)Flask基础

    知识点回顾 1.flask依赖wsgi,实现wsgi的模块:wsgiref(django),werkzeug(flask),uwsgi(上线) 2.实例化Flask对象,里面是有参数的 app = F ...

  9. HDFS的工作流程分析

    HDFS的工作机制 概述 HDFS集群分为两大角色:NameNode.DataNode NameNode负责管理整个文件系统的元数据 DataNode 负责管理用户的文件数据块 文件会按照固定的大小( ...

  10. 前端基础(html)

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...