二、字符串 String
二、字符串 String
String 不是基本数据类型,是一个用final 修饰的最最最最最最常用的引用数据类型!
小拓展:
String
为什么可以直接赋值为一个字符串?
1、存储结构
底层就是一个 char数组
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** 该值用于字符存储. */
private final char value[];
/** 缓存字符串的哈希码 */
private int hash; // 默认为0
}
2、4个重要(必须知道)构造
就 JDK 1.8 而言,String 有 16 个构造方法(其中有 2 个是废弃的)
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/* 以 String 为参数 */
public String(String original) {
this.value = original.value;
this.hash = original.hash;
}
/* 以 char[] 为参数 */
public String(char value[]) {
this.value = Arrays.copyOf(value, value.length);
}
/* 以 StringBuffer 为参数 */
public String(StringBuffer buffer) {
synchronized(buffer) {
this.value = Arrays.copyOf(buffer.getValue(), buffer.length());
}
}
/* 以 StringBuilder 为参数 */
public String(StringBuilder builder) {
this.value = Arrays.copyOf(builder.getValue(), builder.length());
}
}
3、String.equals
String.equals 重写了 Object.equals
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
public boolean equals(Object anObject) {
// 对象引用相同直接返回true
if (this == anObject) {
return true;
}
// 必须是String类型才有比较的必要
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
// 把两个字符串转成char[]逐一比对
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
}
4、常用方法
indexOf()
:返回第一次出现的位置,没有返回-1lastIndexOf()
:返回最后一次出现的位置,没有返回-1contains()
:判断包含toUpperCase()
:转至大写toLowerCase()
:转至小写length()
:返回字符串你长度trim()
:去掉首尾空格.replace()
:替换split()
:拆分数组join()
:字符串数组转字符串endsWith()
:判断结尾包含startsWith()
:判断起始包含equalsIgnoreCase()
:忽略大小写比较isEmpty()
:判空.substring()
:截取
5、为何 final 修饰
对于这样设计的好处,Java语言之父 James Gosling的回答是:
他会更倾向于使用final;因为它能够缓存结果,当你在传参时不需要考虑谁会修改它的值
如果是可变类的话,则有可能需要重新拷贝出来一个新值进行传参,这样在性能上就会有一定的损失
迫使 String类设计成不可变的另一个原因是安全
- 安全
- 高效
6、String、StringBuilder、StringBuffer
StringBuffer 、StringBuilder 都是操作自身的 char[] 来实现字符串的操作;String每次修改都是赋值一个全新的字符串,之前的字符串依然存在,但是很快会被当成垃圾回收掉。
StringBuffer 使用 synchronized 来保证线程安全
String 常用两种创建方式:
/**
* s1先去字符串常量池查看是否有 "aaa" 字符串,如果有直接返回常量句柄;
* 如果没有此字符串,先在字符串常量池中创建这个字符串,然后再返回常量句柄
*/
String s1 = “aaa”;
/**
* s2直接在堆上开辟一个空间,存放 "aaa",只有调用了intern()方法才会把这个
* 字符串存到字符串常量池
*/
String s2 = new String(“aaa”);
// 验证
System.out.println(s1 == s2); // false
String s3 = s2.intern();
System.out.println(s1 == s3); // true