在java的程序中,对字符串的操作是最常见的行为,所以让我们一起了解它吧
1、String
- 首先我们要明确,String并不是基本数据类型,而是一个对象,并且是不可变的对象。(这里说一下:它虽然不是基本数据类型,但是它在参数传值上与基本一样是数值传递)
public final class String
extends Object
implements Serializable, Comparable<String>, CharSequence
String类表示的字符串。java程序中的所有字符串,如 "abc",实现这个类的实例。
字符串是常量,它们的值不能被创建后改变。支持可变字符串字符串缓冲区。
查看源码就会发现String类为final型的(当然也不可被继承),
而且通过查看JDK文档会发现几乎每一个修改String对象的操作,实际上都是创建了一个全新的String对象。
2.我们在初始化String的时候,就要区别:空串””、null、new String()三者的区别
2.1空串也是字符串,JVM会为它分配内存空间的。
2.2 null 表示string还没有new ,也就是说对象的引用还没有创建,也没有分配内存空间给他.
2.3new String()则说明了已经new了,只不过内部为空,但是它创建了对象的引用,是需要分配内存空间的。
3. 在字符串中存在一个非常特殊的地方,那就是字符串池。每当我们创建一个字符串对象时,首先就会检查字符串池中是否存在面值相等的字符串,如果有,则不再创建,直接放回字符串池中对该对象的引用,若没有则创建然后放入到字符串池中并且返回新建对象的引用。这个机制是非常有用的,因为可以提高效率,减少了内存空间的占用。所以在使用字符串的过程中,推荐使用直接赋值(即String s=”aa”),除非有必要才会新建一个String对象(即String s = new String(”aa”))
4.我们可以在jdk文档中,查看字符串常用的方法
返回值的类型 | 方法名和意思 |
---|---|
char | charAt(int index) 返回指定索引的 char价值 |
int | codePointAt(int index) 返回字符(Unicode代码点)在指定的索引。 |
int | compareTo(String anotherString) 比较两个字符串的字典。 |
int | charAt(int index) 返回指定索引的 char价值 compareToIgnoreCase(String str) 按字典顺序比较两个字符串,忽略大小写的差异。 |
String | concat(String str) 将指定的字符串,此字符串的末尾。 |
boolean | contains(CharSequence s) 如果并且只有当此字符串包含指定的字符序列的字符串值,则返回真值。 |
static String | copyValueOf(char[] data) 相当于 valueOf(char[])。 |
boolean | endsWith(String suffix) 测试如果这个字符串以指定的后缀结束。 |
boolean | equals(Object anObject) 将此字符串与指定的对象比较。 |
byte[] | getBytes(Charset charset) 这 String编码为一个字节序列使用给定的 charset,结果存放到一个新的字节数组。 |
int | hashCode() 返回此字符串的哈希代码。 |
int | indexOf(int ch) 返回在指定字符的第一个发生的字符串中的索引。 |
int | length() 返回此字符串的长度。 |
boolean | matches(String regex) 告诉是否这个字符串匹配给定 regular expression。 |
String | replace(char oldChar, char newChar) 返回从字符串中替换所有出现在 newChar oldChar结果字符串。 |
String | replaceAll(String regex, String replacement) 每个子串替换该字符串的给予更换,给 regular expression比赛 |
String | substring(int beginIndex) 返回一个字符串,这个字符串的子串。 |
char[] | toCharArray() 将此字符串转换为一个新的字符数组。 |
String | trim() 返回一个字符串,它的值是字符串,任何前导和尾随空格删除。 |
static String | valueOf(Object obj) 返回的 Object参数的字符串表示形式. |
5. 接着这里就要说下两个另外两个关于String的类。
5.1、StringBuffer
StringBuffer和String一样都是用来存储字符串的,只不过由于他们内部的实现方式不同,导致他们所使用的范围不同,对于StringBuffer而言,他在处理字符串时,若是对其进行修改操作,它并不会产生一个新的字符串对象,所以说在内存使用方面它是优于String的。
其实在使用方法,StringBuffer的许多方法和String类都差不多,所表示的功能几乎一模一样,只不过在修改时StringBuffer都是修改自身,而String类则是产生一个新的对象,这是他们之间最大的区别。
同时StringBuffer是不能使用=进行初始化的,它必须要产生StringBuffer实例,也就是说你必须通过它的构造方法进行初始化。
在StringBuffer的使用方面,它更加侧重于对字符串的变化,例如追加、修改、删除,相对应的方法:
1、append():追加指定内容到当前StringBuffer对象的末尾,类似于字符串的连接,这里StringBuffer对象的内容会发生改变。
2、insert:该类方法主要是在StringBuffer对象中插入内容。
3、delete:该类方法主要用于移除StringBuffer对象中的内容。
5.2、StringBuilder
StringBuilder也是一个可变的字符串对象,他与StringBuffer不同之处就在于它是线程不安全的,基于这点,它的速度一般都比StringBuffer快。与StringBuffer一样,StringBuider的主要操作也是append与insert方法。这两个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符添加或插入到字符串生成器中。
5.3他们三个之间的区别:
类型 | 可变 | 线程安全 | 操作后的结果 | |
---|---|---|---|---|
String | 字符串常量 | 否 | 是 | 产生新的字符串 |
StringBuffer | 字符串变量 | 是 | 是 | 原字符串内容改变 |
String | 字符串变量 | 是 | 否 | 原字符串内容改变 |
6.字符串拼接的方式
6.1在java中提高了三种拼装的方法:+、concat()以及append()方法。
6.2 (一)+方式拼接字符串
我们知道编译器对+进行了优化,它是使用StringBuilder的append()方法来进行处理的,我们知道StringBuilder的速度比StringBuffer的速度更加快,但是为何运行速度还是那样呢?主要是因为编译器使用append()方法追加后要同toString()转换成String字符串,也就说 str +=”b”等同于
str = new StringBuilder(str).append(“b”).toString();
它变慢的关键原因就在于new StringBuilder()和toString(),这里可是创建了StringBuilder对象,而且每次还需要将其转换成String,速度可想而知的慢?
(二)concat()方法拼接字符串
public String concat(String str) {
int otherLen = str.length();
if (otherLen == 0) {
return this;
}
char buf[] = new char[count + otherLen];
getChars(0, count, buf, 0);
str.getChars(0, otherLen, buf, count);
return new String(0, count + otherLen, buf);
这是concat()的源码,它看上去就是一个数字拷贝形式,我们知道数组的处理速度是非常快的,
但是由于该方法最后是 这样的:return new String(0, count + otherLen, buf);
这同样也创建了字符串对象,这是它变慢的根本原因。
(三)append()方法拼接字符串
public AbstractStringBuilder append(String str) {
if (str == null) str = "null";
int len = str.length();
if (len == 0) return this;
int newCount = count + len;
if (newCount > value.length)
expandCapacity(newCount);
str.getChars(0, len, value, count);
count = newCount;
return this;
与concat()方法相似,它也是进行字符数组处理的,加长,然后拷贝,但是请注意它最后是返回并没有返回一个
新串,而是返回本身,也就说这这个的循环过程中,它并没有产生新的字符串对象。