String
1、String字符串存储
java中的内置类:java.lang.String
- 1、String属于引用数据类型。
- 2、在java当中随便使用双引号括起来的都是String对象。例如:“ abc ”。
- 3、java规定字符串不能改变。
- 4、在JDK当中双引号括起来的字符串,例如:“ abc ”,都是直接存储在方法区的字符串常量池当中的。
- 5、垃圾回收器是不会释放字符串常量的。
String s1="abcdef";
String s2="abcdef"+"xy";
//凡是双引号括起来的都在字符串常量池当中有一份
//new对象的时候一定在堆内存当中开辟空间
String s3=new String("xy");
public class Test03 {
public static void main(String[] args) {
String s1="hello";
String s2="hello";
System.out.println(s1==s2);//结果是true
}
}
- 上面这段代码的结果是true,因为hello是保存在方法区的字符串常量池当中,所以这个hello不会新建(因为对象以及存在了)
String x=new String("xyz");
String y=new String("xyz");
System.out.println(x==y);//结果是false
- 上面这段代码的结果是false,因为双等号保存的是变量当中的内存地址。
- 因此对于字符串对象来说,不能使用双等号进行比较。
System.out.println(x.equals(y));
- 上面的代码:使用equals方法比较字符串对象可以得到相等的值。
String k=new String("testString");
System.out.println("testString".equals(k));
- 上面的代码当中可以在"testString"字符串后面加引用的原因是:"testString"字符串是一个String的字符串对象,只要是对象都能调用方法。
2、面试题
下面这段代码一共创建了几个对象?
String x=new String("xyz");
String y=new String("xyz");
分析:一共创建了三个对象。
- 方法区字符串常量池中有1个:“hello”
- 堆内存当中有两个String对象
3、String类中的构造方法
String s1="hello world";
System.out.println(s1);
s1这个变量当中保存的是一个内存地址,按理说应该输出的是一个内存地址,但是输出的是保存的字符串,说明String已经重写了toString()方法。
- 1、将char数组全部转换成字符串:
char[] chars={'我','是','中','国','人'};
String s4=new String(chars);
System.out.println(s4);
- 2、将char数组的一部分转换成字符串:
char[] chars={'我','是','中','国','人'};
String s4=new String(chars);
System.out.println(s4);
String s5=new String(chars,2,3);
System.out.println(s5);
4、String当中的常用方法
1、char charAt(int index)
:获取字符串当中的字符
//1、char charAt(int index)
char c="中国人".charAt(1);
System.out.println(c);
2、int compareTo(String anotherString)
:比较字符串之间的大小
- 拿字符串第一个字母和后面字符串的第一个字母比较,能判定就不再比较了。
int result="abc".compareTo("abc");
System.out.println(result);//0
int result2="abcd".compareTo("abce");
System.out.println(result2);//-1
int result3="abce".compareTo("abcd");
System.out.println(result3);//1
3、boolean contains(CharSequence s)
:判断前面的字符串是否包含后面的子字符串
//3、boolean contains(CharSequence s)
//判断前面的字符串是否包含后面的子字符串
System.out.println("hello.java".contains(".java"));
4、boolean endsWith(String suffix)
:判断当前字符串是否以某个字符串结尾
//4、boolean endsWith(String suffix)
//判断当前字符串是否以某个字符串结尾
System.out.println("test.txt".endsWith(".java"));
5、boolean equals(Object anObject)
:比较两个字符串必须使用equals方法,不能使用==
//5、boolean equals(Object anObject)
//比较两个字符串必须使用equals方法,不能使用==
System.out.println("abc".equals("abc"));
6、boolean equalsIgnoreCase(String anotherString)
:判断两个字符串是否相等,并且同时忽略大小写
//6、boolean equalsIgnoreCase(String anotherString)
//判断两个字符串是否相等,并且同时忽略大小写
System.out.println("ABC".equalsIgnoreCase("abc"));
7、byte[] getBytes()
:将字符串对象转换成字节数组
//7、byte[] getBytes()
//将字符串对象转换成字节数组
byte[] bytes="abcdef".getBytes();
for(int i=0;i<bytes.length;i++){
System.out.println(bytes[i]);
}
8、int indexOf(String str)
:判断某个字符串在当前字符串中第一次出现的索引
//8、int indexOf(String str)
//判断某个字符串在当前字符串中第一次出现的索引
System.out.println("abwjaojavaeajfeaf".indexOf("java"));
9、boolean isEmpty()
:判断某个字符串是否为空字符串
//9、boolean isEmpty()
//判断某个字符串是否为空字符串
String a="";
System.out.println(a.isEmpty());
10、int length()
:判断数组长度是length属性,判断字符串长度是length()方法
//10、int length()
//判断数组长度是length属性,判断字符串长度是length()方法
System.out.println("abc".length());
11、int lastIndexOf(String str)
:判断某个字符串在当前字符串中最后一次出现的索引
//11、int lastIndexOf(String str)
//判断某个字符串在当前字符串中最后一次出现的索引
System.out.println("dsfnisnirsjavashvljava".lastIndexOf("java"));
12、String replace(CharSequence target,CharSequence replacement):
替换字符串
//12、String replace(CharSequence target,CharSequence replacement)
//String的父接口就是:CharSequence
//替换字符串
String s="http://www.baidu.com".replace("http://","https://");
System.out.println(s);
13、String[] split(String regex)
:根据指定字符拆分字符串
//13、String[] split(String regex)
//拆分字符串
String[] ymd="1980-1-11".split("-");
for(int i=0;i< ymd.length;i++){
System.out.println(ymd[i]);
}
14、 Boolean startWith(String prefix):
判断某个字符串是否以某个子字符串开始
//14、 Boolean startWith(String prefix)
//判断某个字符串是否以某个子字符串开始
System.out.println("czcldncscsfz".startsWith("csc"));
15、String substring(int beginIndex):
截取字符串
16、String substring(int beginIndex,int endIndex)
:重载的方法,遵循左闭右开
//15、String substring(int beginIndex)
//截取字符串
System.out.println("snfkjnvskgibqp".substring(7));
//16、String substring(int beginIndex,int endIndex)
//重载的方法,遵循左闭右开
System.out.println("snvosnovlea".substring(7,10));
17、char[] toCharArray():
将字符串转换成char数组
//17、char[] toCharArray()
//将字符串转换成char数组
char[] chars="我是中国人".toCharArray();
for(int i=0;i<chars.length;i++){
System.out.println(chars[i]);
}
18、String toLowerCase
:字符串转换为小写(与之相对应的是:toUpperCase)
//18、String toLowerCase:字符串转换为小写
System.out.println("svdnleqqSBVKLEQ".toLowerCase(Locale.ROOT));
19、String trim()
:去除字符串前后空白
//19、String trim():去除字符串前后空白
System.out.println(" wsiug vsovhw ".trim());
20、String当中只有一个方法是静态的,不需要new对象:这个方法叫做valueOf
- valueOf的作用:将非字符串转换成字符串
String s1=String.valueOf(new Customer());
System.out.println(s1);//没有重写toString方法之前调用的是内存地址
得到的结果是内存地址
- 在Class类当中重写了toString方法之后:
class Customer{
public String toString() {
return "我是VIP客户!";
}
}
知道了valueOf就可以理解为什么在输出引用的时候,调用的是他的toString方法了:
-
查看源码的方法:在代码上面按住Ctrl即可跳转。
-
本质上
System.out.println
在输出任何数据的时候,都会先转换成字符串。 -
能够打印在控制台上面的都是字符串,因为都会使用valueOf方法。
5、String.Buffer
-
在实际开发当中,如果需要字符串频繁的拼接,会出现问题。因为java中的字符串是不可变的,每一次拼接都会产生新的字符串。这样会浪费内存空间,会占用大量的方法区内存。
-
如果以后需要进行大量的字符串拼接操作,建议使用JDK当中自带的:
- java.lang.StringBuffer
- java.lang.StringBuilder
-
StringBuffer底层实际上是一个byte[ ]数组。往StringBuffer中放字符串,实际上是放在了byte数组里面了。
-
StringBuffer的初始化容量是16。
public static void main(String[] args) {
//创建一个初始化容量为16的byte数组。(字符串缓冲区对象)
StringBuffer stringBuffer=new StringBuffer();
//拼接字符串,以后拼接字符串统一调用append方法
stringBuffer.append("a");
stringBuffer.append("b");
stringBuffer.append("c");
stringBuffer.append(3.14);
//append方法底层在进行追加的时候,如果byte数组满了,就会自动扩容
System.out.println(stringBuffer.toString());
}
- 如何优化StringBuffer的性能?
- 在创建StringBuffer的时候尽可能给定一个初始化容量,最好减少底层数组的扩容次数
//指定初始化容量的StringBuffer对象
StringBuffer s=new StringBuffer(100);
6、StringBuilder
- 使用StringBuilder也可以完成字符串拼接的操作
StringBuilder和StringBuffer的区别:
- StringBuffer中的方法都有:synchronized关键字修饰,表示StringBuffer在多线程环境下运行是安全的。
- StringBuilder中的方法都没有使用synchronized关键字修饰。StringBuilder在多线程环境下使用是不安全的。