在jdk1.8中
-
public final class String extends Object implements Serializable, Comparable<String>, CharSequence
最终类,不可被继承
java 程序中的所有字符串,如“abc",是String类的实例。
特征:字符串是常量,他们的值不能被创建后改变
public final class String implements java.io.Serializable, Comparable<String>, CharSequence { /** The value is used for character storage. */ private final char value[];
主要是字符串创建的时候,在底层存储的是字符数组,而这个字符数组被final修饰的,所以字符串的存储地址无法改变,然而我们又知道被final修饰的数组,
我们还是可以拿到数组中的元素然后改变,但是这个字符数组又被private修饰,那么我们就不能从外界调用到此字符数组,更不能改变它的值,这就导致了字符串
在创建后无法被改变(地址值和字符数组中的元素值都不能改变)。
java中所有的字符串存放的就是方法区的运行常量池
java中的所有的常量都存储在运行常量池中,字符串也存储在其中,但是字符串底层是由字符串数组实现的
所以在常量池里只是在存储指向字符数组的地址引用,其他所有的常量直接存储的是真实值。
publ
ic static void main(String[] args) { String s1="ab"; //s1指向方法区常量池地址值 String s2=new String("ab"); //s2指向堆内存地址值
String s3="ab"; //如果常量池中已经出现的字符串和后面的字符串重复了,和s1共用一个字符串常量空间 String s4="a"+"b";//如果等号右边参与运算操作的都是常量,那么java在编译时期就会进行优化,优化的结果就是计算出最后结果再进行赋值 String s5="a"; s5=s5+"b";//字符串和字符变量拼接的时候是通过 一个StringBuilder对象new StringBuilder("a").append("b").toString();来拼接的,因为最后要赋值给s5,所以要.toStirng(),返回的是新的字符串 s5后指向的时堆内存 System.out.println(s1==s2);//false System.out.println(s1==s3);//true System.out.println(s1==s4);//true System.out.println(s1==s5);//false System.out.println(s2==s5);//false }
1. s1==s2为false 两个指向不同区域,地址值不一样
2.s1==s3 true
4.
String s5="a";s5=s5+"b";
字符串共享 :已经创建的字符串和之后的字符串重复了,就共用之前已经创建的字符串。
StringBuilder
string底层是由StringBuilder来实现的拼接(先把字符串底层字符数组的元素复制一份放到StringBuilder的可变数组中进行扩容(拼接),得到的搭配的拼接结果就是新的可变字符数组,再由这个字符数组转成一个新的字符串(就是把这个新的字符数组的元素拷贝一份放到一个新的不可改变的数组里)
我们简单的拼接是用"+"拼接,就比如下面这行代码
String s="a";
String s5="a";s5=s5+"b"; //new StringBuilder("a").append("b").toString();
一共再底层创建了5个对象 对象存储再堆中
+拼接和StringBuilder拼接的效率
空间复杂度
String[] str={100个元素};
1.+拼接
String s="";
for(int i:str){
s+=i;//一次循环创建3个对象
}
一共创建了301个对象
2.StringBuilder拼接
StringBuilder sb=new StringBuilder();
for(int i:str){
sb.append(i);}//一次循环创建1个对象
String s=sb.toString();
一共创建了102个对象
时间复杂度
package day13; public class Demo { public static void main(String[] args) { //返回的是1970.1.1到今天的毫秒值 long start=System.currentTimeMillis(); /*String str=""; //耗时3436毫秒 for(int i=0;i<100000;i++) { str+="a"; }*/ StringBuilder s=new StringBuilder(); for(int i=0;i<100000;i++) //耗时2毫秒 { s.append("a"); } long end=System.currentTimeMillis(); System.out.println(end-start); } }
StringBuilder是用来拼接字符串的,出现再JDK1.5 他的效率很快但是是线程不安全的
StringBuffer是和StringBuilder一样也是拼接字符串,出现再JDK1.0 但是StringBuffer拼接效率较低 但是线程安全
String s="abc"; System.out.println(s); 照理来说输出对象就是输出对象的存放地址,但是字符串输出的确是字符串的内容,这是因为java中字符串虽然是有地址的,但是java不提供获取字符串地址的功能,只是返回字符串内容。