1、相等性规则
==比较运算符
1) ==比较基本数据类型,判断的是值是否相等(基本数据类型只能用“==”比较)
2)==比较引用类型,判断的是内存地址是否相等
equals()方法
1)默认的equals方法与==一样,比较的是内存地址
2)按照自己的相等性规则进行比较,需要自定义equals方法(String类的equals方法比较的是值,重写过)
2、String类型
String类型是一个引用类型,即栈中存放对象名和对象的引用,堆中存放String对象;
String类型的对象,底层实际是一个final修饰的char类型的数组。String类也加也final关键字修饰
2.1创建String类型的对象
//第一种String类构造方法创建
/*
这种创建方式,就是创建一个String类型的对象,是在内存中新申请一块内存*/
String a = new String ("abc" );
//第二种字面值的方式创建 /*
这种创建方式,会把值存放到字符串常量池中
字符串常量池,可以理解为一个String的数据集,它是在堆内存中开辟的一块特殊内存*/
//第二种字面值的方式创建/*
这种创建方式,会把值存放到字符串常量池中
字符串常量池,可以理解为一个String的数据集,它是在堆内存中开辟的一块特殊内存*/
方法 | 返回值 | 作用 | 示例 |
equals() | boolean | 比较字符串是否相等 | String a="hi"; String b="hello"; boolean tar=a.equals(b); |
length() | int | 返回字符串的长度 | int len=a.length(); |
trim() | String | 去除字符串两端的空格 | String b=a.trim(); |
replance() | String | 替换字符串中的指定字符(串),把能匹配上的全部替换 | a.replance(s1.s2); s1:被替换的字符 s2:替换字符 |
concat() | String | 拼接字符串 | a.concat("123"); |
toLowerCase() | String | 字符串转小写 | a.toLowerCase(); |
toUpperCase() | String | 字符串转大写 | a.toUpperCase(); |
split() | String | 根据指定字符把字符串切分成数组,返回String[] | String a="a,b,c"; String[] arr=a.split(","); |
contains() | boolean | 判断字符串中是否包含指定字符 | a.contains("a"); |
substring(x) | String | 根据下标截取字符串,从指定下标到字符串末尾 | substring(int x); String b=a.substring(1); |
substring(1,2) | String | 截取下标范围内的字符串,从开始下标到结束下标(左闭右开) | substring(int s,int e); |
indexOf() | int | 截取指定字符在字符串中的下标 | int index=a.indexOf("a"); |
lastIndexOf() | int | 获取最后一个指定字符的下标 | int lastindex=a.indexOf("a"); |
charAt() | char | 获取指定下标的字符 | char c=a.charAt(1); |
isEmpty() | boolean | 判断字符串是否为空 | boolean tar=a.isEmpty(); |
toCharArray() | char[] | 将字符串转为字符数组 | char[] d=a.toCharArray(); |
String.valueOf() | String | 将变量转为String类型 | int a=1; String b=null; b=String.valueOf(a); |
String类的静态方法format() 能用来创建可复用的格式化字符串
float f1= 1.1f;
int i2 = 10; .
String s3 = "hello";
String str = String.format("浮点型%f整型%d字符串%s", fl, i2, s3);
System.outprintin(str); //打印:浮点型1.00000整型10字符串hello
public class r {
public static void main(String[] args) {
String a="a b c";
String [] b=a.split("");
System.out.println(b.length);
System.out.println(Arrays.toString(b));
String s9 =",A,B,C,";
String[] arr3 = s9.split(",");//默认第一个,之前空的也算一个,但最后一个,之后的空的不算
System.out.println(arr3.length);
System.out.println( Arrays.toString(arr3));
}
5
[a, , b, , c]
4
[, A, B, C]
3、字符串常量池
3.1字符串常量池的设计思想
字符串的分配,和其他的对象分配一样,耗费高昂的时间与空间代价作为最基础的数据类型,大量频繁
的创建字符串,极大程度地影响程序的性能
3.2常量池工作原理
JVM为了提高性能和减少内存开销,在实例化字符串常量的时候进行了一些优化为字符串开辟一个字符串常量池,类似于缓存区
创建字符串常量时,首先检查字符串常量池是否存在该字符串
存在该字符串,返回引用实例,不存在,实例化该字符串并放入池中
3.3实现的基础
实现该优化的基础是因为字符串是不可变的(firal),可以不用担心数据冲突进行共享
运行时实例创建的全局字符串常量池中有一个表,总是为池中每个唯一的字符串对象维护一个引用,这就意味着它们一直引用着字符串常量池中的对象,所以,在常量池中的这些字符串不会被垃圾收集器回收
4、StringBuffer与StringBuilder
String和StringBuffer、StringBuilder他们都可以存储和操作字符串,即包含多个字符的字符串数据。String类是字符串常量,是不可更改的常量。而StringBuffer/StringBuilder是字符串变量,它的对象是可以扩充和修改的。
特点:
1)修改Strirg对象的值,内存地址会发生改变;
2)StringBuffer和StringBuilder类的对象能够被多次的修改,并且不产生新的对象,即内存地址不变;
3)StringBuffer是线程安全的,StringBuilder是线程不安全的;
4) StringBuilder的执行速度比StringBuffer快;
常用方法:
append() | StringBuffer | 拼接字符串到末尾 | StringBuffer a; a.append("abc"); |
reverse() | StringBuffer | 将字符串中的字符顺序反转 | StringBuffer a; a.reverse(); |
delete() | StringBuffer | 删除字符串中指定下标范围的字符串 | a.delete(1,3); |
insert() | 在字符串指定下标位置插入字符 | a.insert(1,"efd"); | |
replace() | 替换指定索引区间的字符串(左闭右开),是替换这个区间的串,而不是将每个字符替换 | a.replace(1,3,"hul") | |
length() | int | 字符串长度 | a.length(); |
toString() | 转成String字符串 | a.toString(); |
5、关于字符串的补充
1、+号拼接
String s1 = "ab";
String s2 = "cd";
String s3= s1 + s2;//new一个新对象,s3不进常量池
String s4 = s1 + "cd";//也不进常量池
String s5 = new String("ab") + new String("cd");
String s6 = new String("ab") + "cd";
//+拼接字符串时程序是 如何运行的?
//首先创建StringBuilder对象,然后调用append
//需要注意:
String s7 = "ab" + "cd";
//以上s7创建的字符串对象在编译时就变成了"abcd"
//所以字符串常量池中只创建”abcd"的对象不会分别创建“ab"和"cd"
2、intern()方法
因为不是所有的字符串创建方式都会在常量池中生成对应的字符串,而intern方法用 于根据所给的字符串在
常量池中创建对应的字符串。jdk1.7以后,调用interm方法时, 如果该字符串已经存在于常量池中,则将常
量池中的引用直接返回;如果不存在,则在常量池中生成一个对原字符串的引用。
String s1 = "abcd";
String s2 = str1. intern();
System. out.printn(s1 == s2);
//结果为true两者都指向常量池中的abcd
String s3 = new String("abcd");
String s4 = s3. intern();
System. out. printIn(s3 == s4);
//结果为false s3指向堆 s4指向常量池中的
String al = new String("abc");
Strina a2 = al + "d";
//String aa = a2. intern();
String a3 = "abcd";
System. out. println(a2 == a3);//false
//如果打开intern()方法的代码就为true
//此时常量池中的" abcd"是个引用,指向a2的对象