一.String
- 字符序列:把多个字符按照一定的顺序排列起来,
字符串:把多个字符串连起来. - 字符串的分类:
不可变的字符串:String当前对象创建完毕之后,该对象的内容(字符序列)是不能改变的,一旦内容改变
就是一个新的对象. - 可变的字符串:StringBuilder/StringBuffer:当对象创建完毕后,该对象的内容可以发生改变,当内容
发生改变的时候,对象保持不变 - 字符串的本质(底层):
String str = "ABCD";//定义一个字符串对象,等价于
char[] cs = new char[]{'A','B','C','D'};
- String对象的创建:
- 直接赋值一个字面量: String str1 = “ABCD”;
- 通过构造器创建: String str2 = new String(“ABCD”);
- String对象的空值:
- 表示引用为空(null):String str1 = null; 没有初始化,没有分配内存空间
- 内容为空字符串: String str2 = “”; 有初始化,分配了内存空间,只是没有内容。
- 判断字符串非空:
- 引用不能为空(null);
- 内容不能为空("");
- 字符串的比较操作:
- 使用“==”号: 只能比较引用的内存地址是否相同
- 使用equals方法: 在Object类中和“==”相同,建议子类覆盖equals方法去比较自己的内容。
- String类覆盖equals方法,比较的是字符内容。
面试题1:
- 下列代码分别创建了几个String对象。
String str1 = "ABCD";
最多创建一个String对象,最少不创建Srting对象。
如果常量池中,以及存在“ABCD”,那么str直接引用,此时不创建String对象。
否则,先在常量池先创建"ABCD"内存空间,再引用
String str2 = new String("ABCD");
最多创建两个String对象,至少创建一个String对象。
new关键字:绝对会在堆空间,创建内存区域,所以至少创建一个String对象
面试题2:
- 说说str1与其他对象的引用是否相等:
-
String对象比较:
- 单独使用“”引号创建的字符串都是直接量,编译期就已经确定存储到常量池中
- 使用new String(“”)创建的对象会存储到堆内存中,是运行期才创建
- 使用只包含直接量的字符串连接符如“aa”+"bb"创建的也是直接量,编译期就能确定存储到常量
池中。 - 使用包含String直接量(无final修饰符)的字符量表达式(“aa”+s1)创建的对象是运行期才创
建的,存储到堆中;
通过变量、调用方法去连接字符串,都只能在运行时期才能确定变量的值和方法的返回值,不
存在编译优化操作。
-
String中的常用方法:
- String的创建和转换:
byte[] getBytes():把字符串转换为byte数组 String(byte[] bytes):把byte数组转换为字符串 char[] toCharArray():把字符串转换为char数组 String(char[] value):把char数组转换为字符串
- 获取字符串信息
int length() 返回此字符串的长度 char charAt(int index) 返回指定索引处的char值 int indexOf(String str) 返回指定字字符串在此字符串中第一次出现出的索引 int lastIndexOf(String str) 返回指定子字符串在此字符串中最右边出现处的索引
- 字符串比较判断
boolean equals(Object anObject) 此字符与指定的对象比较 boolean equalsIgnoreCase(String anotherString) 将此String与另一个String比较,不考虑大小写 boolean contentEquals(CharSequence cs) 底层和equals相同
- 字符串大小写转换
String toUpperCase();//小转大 String toLowerCase();//大转小
新建StringDemo.java
public class StringDemo {
public static void main(String[] args) {
buiderString();
getStringInfo();
equalsString();
toUpper_Lower();
}
//大小写转换
private static void toUpper_Lower() {
System.out.println("ABCsdsfsf".toUpperCase());
System.out.println("ABCsdsfsf".toLowerCase());
}
//比较String
private static void equalsString() {
String s = new String( "ABCD");
String s2 = new String( "ABCD");
System.out.println(s == s2);//false
System.out.println(s.equals(s2));//true
System.out.println("ABCD".equals("abcd"));//false
System.out.println("ABDC".equalsIgnoreCase("abcd"));//true
System.out.println("ABCD".contentEquals("ABCD"));//true
System.out.println("----------------------");
}
//获取String信息
private static void getStringInfo() {
/**
int length() 返回此字符串的长度
char charAt(int index) 返回指定索引处的char值
int indexOf(String str) 返回指定字字符串在此字符串中第一次出现出的索引
int lastIndexOf(String str) 返回指定子字符串在此字符串中最右边出现处的索引
*/
System.out.println("ABS DG ".length());
//返回指定索引的值
System.out.println("ABCD E".charAt(4));
//返回指定字字符串在此字符串中第一次出现出的索引
System.out.println("ADCSDIA".indexOf("DI"));
//返回指定子字符串在此字符串中最右边出现处的索引
System.out.println("AKDJLAS".lastIndexOf("JL"));
System.out.println("----------------------");
}
//String与char[]和byte[]转换
private static void buiderString() {
//字符串与byte数组的转换
String s = "ABCD";
System.out.println(Arrays.toString(s.getBytes()));
System.out.println(new String(s.getBytes()));
//字符串与char数组的转换
System.out.println(Arrays.toString(s.toCharArray()));
System.out.println(new String(s.toCharArray()));
System.out.println("----------------------");
}
}
String练习操作
新建StringDemo2.java
public class StringDemo1 {
public static void main(String[] args) {
getExtension();
firstCapital();
}
//首字母改为大写
private static void firstCapital() {
String s = "adsdSSDD";
String str = s.substring(0, 1).toUpperCase();//截取首字母变为大写
str += s.substring(1);//截取首字母后的字符串拼接
System.out.println(str);
}
//获得Hello文件的拓展名
private static void getExtension() {
String s = "Hellor.java;Text.java;Hello.text;Hello.class";
//1)获取文件名和拓展名
String[] s1 = s.split(";");
//2)获取Hello文件
for (String str : s1) {
//System.out.println(str.substring(0,str.indexOf(".")));//截取索引0到“.”之间的字符串
if ("Hello".equals(str.substring(0,str.indexOf(".")))) {
System.out.println(str.substring(str.lastIndexOf(".")));
}
}
}
}
String工具类的封装
新建StringUtil.java
public class StringUtil {
//私有化构造器,防止new对象
private StringUtil() {}
//判非空
public static boolean nonNull(String s) {
return s != null && s.trim() != "";
}
//判空
public static boolean stringNull(String s) {
return !nonNull(s);
}
}
新建测试类StringUtilDemo.java
public class StringUtilDemo {
public static void main(String[] args) {
boolean b = StringUtil.nonNull("");
System.out.println(b);
String s = null;
b = StringUtil.stringNull(s);
System.out.println(b);
}
}
二.StringBuilder
-
分别使用String/StringBuffer/StringBuilder类拼接30000次字符串,对比各自耗时:
- String做字符串拼接时,性能极地(耗时),原因String时不可变的,每次内容改变都会在内存创建新的
的对象.
String 3997ms StringBuffer 5ms StringBuilder 2ms
新建StringTime.java public class StringTime { public static void main(String[] args) { stringTime(); StringBufferTime(); StringBuilder(); } //使用StringBuilder拼接30000次耗时 private static void StringBuilder() { StringBuilder str = new StringBuilder(90); int i = 0; Long l = System.currentTimeMillis(); while (i < 30000) { str.append("a"); i++; } l = System.currentTimeMillis() - l; System.out.println(l); } //使用StringBuffer拼接30000次耗时 private static void StringBufferTime() { StringBuffer str = new StringBuffer(""); int i = 0; Long l = System.currentTimeMillis(); while (i < 30000) { str.append(i); i++; } l = System.currentTimeMillis() - l; System.out.println(l); } //拼接String30000次的时间 private static void stringTime() { String str = ""; int i = 0; Long l = System.currentTimeMillis(); while (i < 30000) { str += i; i++; } l = System.currentTimeMillis() - l; System.out.println(l); } }
- String做字符串拼接时,性能极地(耗时),原因String时不可变的,每次内容改变都会在内存创建新的
-
结论:以后拼接字符串,通通使用StringBuilder/Stringffer,不要使用String
StringBuffer和StringBuilder都表示可变的字符串,功能都是相同的. -
唯一区别:
- StringBuffer:StringBuffer中的方法都使用synchronized修饰符,表示同步的,在多线程并发的时候来保
证线程安全,保证线程安全的时候性能较低. - StringBuilder:StringBuilder中的方法都不使用synchronized修饰符,不安全,但是性能较高.
- 使用StringBuilder无参构造器,在底层创建了一个长度为16的4. char数组:
char[] value = new char[16];
- StringBuffer:StringBuffer中的方法都使用synchronized修饰符,表示同步的,在多线程并发的时候来保
此时该数组只能存储16个
新建StringBuilderDemo.java
public class StringBuilderDemo {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder (20);
//链式编程,拼接字符
sb.append("a").append("E").append("p").append("asdjk");
System.out.println(sb);
//删除指定索引的字符
sb.deleteCharAt(1);
System.out.println(sb);
//删除指定索引之间的字符
sb.delete(2, 5);
System.out.println(sb);
}
}