1.String 类型的概述

Java中String就是Unicode字符序列,例如,字符串“Java\u2122”由5个Unicode字符J、a、v、a和 ™ 组成。不像C/C++中,字符串只是字符数组,Java中字符串String是一个java.lang包中的类。

但是,在Java中String和普通的类不一样,是一个特殊的类:

  • String可以直接使用双引号""进行赋值,而不用调用构造函数。
  • '+'可以拼接两个字符串,但是其他对象不能使用'+'。
  • String是不可变的,也就是说,String对象一旦创建就不能被修改。例如,toUpperCase() 方法创建并返回一个新字符串,而不是修改原理字符串的内容。

String类型的常用方法总结:

// 长度
int length() // 返回字符串的长度
boolean isEmpty() // 判断长度是否==0 // 比较
boolean equals(String another) // Java中不能使用 '==' 或者 '!=' 来比较两个字符串
boolean equalsIgnoreCase(String another)
int compareTo(String another) // 返回 0 如果字符串相同;< 0 如果字典序小于another;否则 > 0
int compareToIgnoreCase(String another)
boolean startsWith(String another)
boolean startsWith(String another, int fromIndex) // 在fromIndex位置开始
boolean endsWith(String another) // 检索 & 索引下标
int indexOf(String search)
int indexOf(String search, int fromIndex)
int indexOf(int character)
int indexOf(int character, int fromIndex)
int lastIndexOf(String search)
int lastIndexOf(String search, int fromIndex)
int lastIndexOf(int character)
int lastIndexOf(int character, int fromIndex) // 截取字符串的字符或一部分字符串(子串)
char charAt(int index) // 下标从 0 到 length - 1
String substring(int fromIndex)
String substring(int fromIndex, int endIndex) // 包前不包后 // 根据原字符串创建一个新字符串或字符数组
String toLowerCase()
String toUpperCase()
String trim() // 返回一个移除前后空白的新字符串
String replace(char oldChar, char newChar) // 返回一个替换后的字符串
String concat(String another) // 字符串拼接
char[] toCharArray() // 返回一个字符串数组
void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) // 复制到 dst 字符数组中 // 静态方法,将基本类型转换为字符串
static String valueOf(type arg) // type可以是基本类型或者字符数组 // 静态方法,将字符串进行格式化输出
static String format(String formattingString, Object... args) // 类似于printf() // 正则表达式
boolean matches(String regex)
String replaceFirst(String regex, String replacement)
String replaceAll(String regex, String replacement)
String[] split(String regex)
String[] split(String regex, int limit)
静态方法 String.format()

这个方法用来输出一个格式化的字符串,类似于 C 系列的 printf() 函数。例如,

String.format("%.1f", 1.234);   // 返回字符串 "1.2"

String.format() 可以非常方便地用来输出一个简单格式的字符串(比如,在 toStirng() 方法中使用)。对于复杂的字符串,使用StringBuffer/StringBuilder加一个Formatter。

2. String 一个特殊的类

因为程序会频繁的使用 String 类型,String 类型在Java中是很特殊的。自然,为了计算性能和存储效率,String 的性能很关键。为了提高提高语言的性能,Java设计者们在面向对象语言中,保留了基本数据类型,而不是一切都是对象。基本数据类型存储在调用栈上,从而占用更少的存储空间,以及更容易维护。而对象实例存储在堆上,需要更复杂的内存管理和更多的存储空间。

为了更好地性能,Java 的 String 被设计成介于基本数据类型和普通类之间的一个特殊类型。Stirng 的特性包括:

  • 用于基本数据类型操作的'+',被 String 重载用来拼接两个字符串。出于软件工程的考虑,Java 不支持操作符的重载。在支持操作符重载的语言中,比如 C++ ,甚至可以将 '+' 重载用来执行减法运算,这会使得代码难以阅读。Java 中 '+' 只被内部重载用于字符串拼接。'+' 并不能用于任意两个对象中,比如 Points 或者 Circles。
  • String 有两种创建方式:直接赋值 或者 通过 new 关键字创建(这种方式不推荐,也不常见)

    举个例子:

    String str1 = "Java is Hot";           // 隐式地通过 String 字面量创建
    String str2 = new String("I'm cool"); // 显式地使用 new 创建

    在第一条语句中,str1 被申明为一个 String 类型引用,并被 String 字面量 "Java is Hot" 初始化。在第二条语句中,str2 被申明为一个 String 类型引用,并通过 new 关键字构造的 "I'm cool" String 对象初始化。

  • Stirng 字面量存储在常量池中,相同内容的字符串是共享的,只会存储一份。通过 new 创建的 String 对象存储在堆上,相同内容的字符串不会共享。

2.1 String 字面量 VS String 对象

如上所述,有两种方式构造 String :通过 String 字面量隐式地构造,或者通过 new 显式地创建。比如:

String s1 = "Hello";              // String 字面量
String s2 = "Hello"; // String 字面量
String s3 = s1; // 相同的引用
String s4 = new String("Hello"); // String 对象
String s5 = new String("Hello"); // String 对象

Java 提供一个特别的机制,字符串常量池,来保存 String 字面量。如果两个 String 字面量内容相同,它们将会在字符串常量池中共享。频繁使用的字符串将会通过这种方式持久地保存。另一方面,通过new 创建的 String 对象被保存在堆中。每个存储在堆上的 String 对象,就像其他对象一样,拥有独立的存储地址。堆上的存储地址不会共享,即使两个 String 对象内容相同。

可以使用 String 类的 equals() 方法比较两个字符串的内容。也可以使用 '==' 来比较两个对象的引用(或者叫指针)。看看下面的代码:

s1 == s1;         // true, 相同的引用
s1 == s2; // true, s1 和 s2 在常量池中共享
s1 == s3; // true, s3 被赋值为 s1 的引用
s1.equals(s3); // true, 内容相同
s1 == s4; // false, 对象引用不同
s1.equals(s4); // true, 内容
s4 == s5; // false, 堆上的引用不同
s4.equals(s5); // true, 内容相同

重点:

  • 在上面的例子中,通过'=='比较两个 String 对象的引用,说明了字符串存储在常量池和存储在堆上的区别。在程序中,使用 (str1 == str2) 来比较两个字符串的内容是逻辑上的错误。
  • String 直接赋值的内容将存储在字符串常量池中。不推荐使用 new 去创建一个堆上的字符串对象。

2.2 String 的不可变特性

因为字符串在常量池中是共享的,Java 的 String 被设计成不可变的。也就是说,一旦 String 被创建,它的内容就不能被修改。否则,其他共享内容的 Stirng 引用将会被无法预料变化影响。类似于 toUpperCase() 的方法就可能修改 String 对象的内容,而实际上它将返回一个新创建的 String 对象,原本的 String 对象引用会被释放,一旦没有引用了,就将会被GC。

因为 String 是不可变的,频繁修改 String 的效率很低(这将创建大量的字符串,并占用内存空间)。比如下面这段代码:

// 效率低的代码
String str = "Hello";
for (int i = 1; i < 1000; ++i) {
str = str + i;
}

如果需要频繁修改字符串,可以考虑使用 StringBuffer 或者 StringBuilder。

3. StringBuffer & StringBuilder

如前所述,字符串是不可变的,因为存储在字符串常量池中的字面量是共享的。修改其中一个字符串的内容,将会对其他共享的字符串产生副作用。

JDK 提供了两个类来支持可变的字符串:StringBuffer 和 StringBuilder(都在核心包 java.lang 中)。StringBuffer 和 StringBuilder 对象跟其他普通对象一样,存储在堆上,不会共享,因此修改它们不会对其他对象产生副作用。

StringBuilder 类是在JDK 1.5中引入的。它基本上与 StringBuffer 一致,除了它是线程不安全的以外。对于单线程的程序来说,StringBuilder 因为没有同步的开销,效率会更高。

必须知道的String知识点的更多相关文章

  1. Javascript:必须知道的Javascript知识点之“单线程事件驱动”

    heiboard: Javascript:必须知道的Javascript知识点之“单线程事件驱动”

  2. 深入理解.net - 4.你必须知道的String

    为什么要单独写string,主要是它太常用了,同时又太特殊了,特殊到CLR对它的处理都和其它对象不一样.简直可以称为VIP用户啊.本文并不是一篇介绍如何使用string的文章,而是旨在阐述string ...

  3. 【源码分析】你必须知道的string.IsNullOrEmpty && string.IsNullOrWhiteSpace

    写在前面 之前自信撸码时踩了一次小坑,代码如下: private static void AppServer_NewMessageReceived(WebSocketSession session, ...

  4. 你必须知道的MySQL知识点

    什么是索引 索引是帮助MySQL高效获取数据的排好序的数据结构 索引数据结构(掌握) 数据结构可视化 前置知识:树的高度越低查询效率越高 二叉树:不能自平衡,极端情况出现倾斜,查询效率和链表类似 红黑 ...

  5. 《jQuery风暴》第2章 必须知道的JavaScript知识

    第2章 必须知道的JavaScript知识 JavaScript是jQuery应用的基础,掌握JavaScript这门语言是使用jQuery的基础条件.本章不会全面细致的讲解JavaScript的全部 ...

  6. 必须知道的ADO.NET 数据库连接池

    http://www.cnblogs.com/liuhaorain/archive/2012/02/19/2353110.html 题外话 通过前几章的学习,不知道大家对ADO.NET有一定的了解了没 ...

  7. C语言学习书籍推荐《你必须知道的495个C语言问题》

    萨米特 (Steve summit) (作者), 孙云 (译者), 朱群英 (译者) 下载地址:点我 <你必须知道的495个C语言问题>以问答的形式组织内容,讨论了学习或使用C语言的过程中 ...

  8. 《你必须知道的.NET》读书笔记一:小OO有大智慧

    此篇已收录至<你必须知道的.Net>读书笔记目录贴,点击访问该目录可以获取更多内容. 一.对象  (1)出生:系统首先会在内存中分配一定的存储空间,然后初始化其附加成员,调用构造函数执行初 ...

  9. 《你必须知道的.NET》读书笔记二:小OO有大原则

    此篇已收录至<你必须知道的.Net>读书笔记目录贴,点击访问该目录可以获取更多内容. 一.单一职责原则 (1)核心思想:一个类最好只做一件事,只有一个引起它变化的原因 (2)常用模式:Fa ...

随机推荐

  1. 一次性清除页面上的所有setInterval

    参考链接:https://www.cnblogs.com/liujinyu/p/3668575.html

  2. solr搜索结果转实体类对象的两种方法

    问题:就是把从solr搜索出来的结果转成我们想要的实体类对象,很常用的情景. 1.使用@Field注解 @Field这个注解放到实体类的属性[字段]中,例如下面 public class User{ ...

  3. Linux题库练习

    转一个Linux的题库供自己学习使用(滑稽) 转自:http://www.linuxdiyf.com/view_202485.html 选择题1 在终端下输入mount -a命令的作用是:CA 强制进 ...

  4. TensorSpace:超酷炫3D神经网络可视化框架

    TensorSpace:超酷炫3D神经网络可视化框架 TensorSpace - 一款 3D 模型可视化框架,支持多种模型,帮助你可视化层间输出,更直观地展示模型的输入输出,帮助理解模型结构和输出方法 ...

  5. [SQL] - 报表查询效率优化

    背景 系统将数据对象JSON序列化后存放到数据库字段中.Report 模块需要获取实时数据对象数值,当前在SQL中进行数值判断的耗时长,效率低. 分析 当前执行效率低主要是程序结构设计的不合理. SQ ...

  6. 用php做管理后台

    最近因处理家庭之事,技术上没有提高,这段时间也陆续的恢复了正常的开发,由于要做一个管理后台,所以在选择语言和架构上搜了不少资料, php 和java 的选择上,后来选择用php作为管理后台开发的语言. ...

  7. Python 解LeetCode:394 Decode String

    题目描述:按照规定,把字符串解码,具体示例见题目链接 思路:使用两个栈分别存储数字和字母 注意1: 数字是多位的话,要处理后入数字栈 注意2: 出栈时过程中产生的组合后的字符串要继续入字母栈 注意3: ...

  8. 学习makefile 的网址

    http://www.ruanyifeng.com/blog/2015/02/make.html http://blog.csdn.net/ruglcc/article/details/7814546 ...

  9. MySQL新项目如何确保上线安全

    大纲 DBA最应该做的事情 新项目开发环境应该注意什么 功能测试和压力测试MySQL DBA关注点 线上环境关注点 业务在大压力情况下,MySQL如何能活下来 DBA最应该做的事情 备份 建议每天全备 ...

  10. docker xfs卡死

    原因 docker在xfs文件系统中,过于频繁create/destory container.pull/push image,当thin pool满时,DeviceMapper后端默认文件系统xfs ...