在 Java 中的字符串属于对象, 那么 Java 中提供了 String 类来创建和操作字符串, 即是使用对象; 因为 String 类修饰的字符一旦被创建就不可改变, 所以当对字符串进行修改的时候, 需要使用到 StringBuffer 和 StringBuilder 类.
String 类
接下来开始使用对象了, 什么是 String 类呢?
是用来修饰字符串的, 字符串是一种特殊的对象, 一旦初始化就不可被改变, 用 String 修饰的字符串变量是不可以被改变的.
例子:
- // 定义一个字符串
- String str = "hello world";
- String str = new String("hello world");
在 Java 中, 我们经常用到字符串, 所以需要学习如何操作字符串. 对于 String 类, 存在 java.lang.String 中, String 类代表字符串, 如何实现字符串的字面值, 就是用此类来实例的.
那么字符串是?
字符串是作为常量, 被双引号包着的为常用, 被初始化即不可被更改. 那么接下来举个例子效果.
- String i = "123";
- System.out.println("i="+i);
- // 结果为
- i=123
如果添加以下
- String i = "123";
- i = "12"
- System.out.println("i="+i);
- // 结果为
- i=12
看到这个效果, 你会认为不是改了吗? 其实不是的, 而是新创建了一个对象而已.
在 String 中, 对象是不可变的, 但可以共享的. 那么怎么理解是共享的呢? 这里引出常量池的概念, 如下:
- // 多个引用指向同一个字符串
- String str1 = "dashu"
- String str2 = "dashu";
- System.out.println(str1==str2);
- // 结果
- true
为 true 代表它们同时指向一个字符串, 即为对象. 创建了一个 str1 对象, 字符串常理为 "dashu", 那么再次创建一个对象时, 常理名相同, 在常量池中发现有相同的 "dashu", 那么就同时指向一个值.
常量池是用来放置一堆常量的, 如果其中有相同的值, 那么就不用再次创建对象, 这是为了节约内存空间, 如果再次创建, 就会浪费内存空间, 第一个创建的字符串放在常量池中, 如果要用的时候, 就拿来用.
展示
- // 内容相同, 但是创建方式不同的情况
- String str3 = "abc"
- String str4 = new String ("abc");
- System.out.println(str3==str4);//false
- System.out.println(str3.equals(str4));//true
- // 结果
- false
- true
其实 str3==str4, 比较的是对象, 而 str3.equals(str4), 比较的是内容. 在代码中只要有 new, 表示在内存中开辟了一个新空间, 所以地址不相同, 即 str3==str4 为 false.
那么这两种创建方式有何不同, 对于 str3 来说, 在内存中只创建了一个对象, 而 str4 就不同了, 而是在内存中有两个对象. 那么怎么理解呢?
str3 就不用说了, 可以知道就创建一个对象, 在 str4 中, 因为有个 new, 在内存中有 new 即为创建了一个对象, new String() 为构造函数, 那么它接收的是一个字符串对象, 那么接收的值是由常量池来的, 常量池中的字符串本身就是一个对象.
一般不会像 str4 中那样创建, 因为浪费内存了, 但常用来存储数组, 字符数组和字节数组. new Stirng(), 所以字符和字节可以转换为字符串.
String 方法
为什么我们要学习 String 呢?
是因为我们需要使用对象, 使用 String 类中的一堆方法. 如果要知道有哪些方法, 可以查一下 API, 要使用时不知道用哪些方法, 那么就可以去查, 用到就查, 也不用每个都记住.
记住字符串是一个对象, 是不可被更改的, 它的一切方法都是围绕着对象的数据而定的. String 类为不可变对象, 一旦被创建, 就不能修改它的数值.
对于上方代码中的例子所示, 已存在的 String 对象, 对其修改都是重新创建一个新的对象, 然后把新的值保存进去而已.
所以不要理解错了下方的代码:
- String i = "123";
- i = "12"
- System.out.println("i="+i);
- // 结果为
- i=12
对于方法可以自行查找 API 试试效果即可, 查找百度 JavaAPI 文档即可下载使用.
StringBuffer
对于字符串是常量, 它的值在创建后时不可以改变的, 但字符串缓冲区支持可变的字符串.
StringBuffer 类为 java.lang 中, StringBuffer 为字符串缓冲, StringBuffer 为线程安全的可变字符序列, 类似 String 的字符串缓冲区, 缓冲区不能改, 但里面可以改, 通过某方法可以改变序列的长度和内容.
StringBuffer 提供了主要的两种方法, 一, append(), 二, inset().
StringBuffer 为一个字符串缓冲区, 相对于一个容器, 长度是可变的, 可以存储任意类型数据, 是将任意数据转变为字符串进行存储, StringBuffer 提供了对数据的很多的操作功能.
例子:
- StringBuffer sb = new StringBuffer();
- sb.append("da");
- sb.append("shu");
- System.out.println(sb);
- //sb.append("da").append("shu");
如果要操作数据, 要转换为字符串. StringBuffer 所有存储的元素都被转成字符串才可使用.
String str = sb.append("da").append("shu").toString();
在指定位置插入元素
sb.insert(2,"hehe");// 插入
StringBuffer 和 StringBuilder 的区别
StringBuilder 为 java.lang 类, 是一个可变的字符序列, 提供了与 StringBuffer 兼容的 API,StringBuffer 和 StringBuilder 方法是一模一样的.
StringBuilder 不同步, 不安全. 如果同时 append(),delete(),insert(), 会导致出错, 多线程访问不安全, 添加修饰 synchronized 即可. 在 jdk1.5 版本后, 推出 StringBuilder 被用作一个 StringBuffer 的简易替换, 用在字符串缓冲区被单个线程使用的时候.
使用 StringBuilder 的出现, 是为了提高效率, 是非同步的, 是对单线程访问效率高, 对于 StringBuffer 是同步的, 对多线程的访问是安全的. 这些是不同点, 相同的是功能一模一样的哦.
来源: http://www.jianshu.com/p/febed3db066d