String是字符串,使用一对""引起来表示
-
String声明为final的,不可被继承
-
String实现了Serializable接口:表示字符串是支持序列化的
-
String实现了Comparable接口:表示String可以比较大小
-
String内部定义了final char[] value 用于存储字符串数据
-
String:代表不可变的字符序列。简称不可变性,不可在原有的字符串位置上进行赋值
-
通过字面量的方式(区别于new)给一个字符串赋值,此时字符串声明在常量池中
String s1 = "abc";//字面量的定义方式
-----------------------------------------
System.out.println(s1 == s2);//比较s1和s2的地址值
7.字符串常量池中不会存储相同内容的字符串
体现:
-
当对字符串重新赋值时,需要重写指定内存区域赋值,不能使用原有的valu进行赋值
-
当对现有字符串进行连接操作,也需要重新指定内存区域重新赋值,不能在原有的value上赋值
-
当调用String的replace()方法时,也需要重新指定内存区域重新赋值,不能在原有的value上赋值
String对象的创建
String str = "hello";
//本质上this.value = new char[0];
String s1 = new String();
//本质上this.value = original.value;
String s2 = new String(Stirng original);
//本质上this.value = Arrays.copeOf(value,value.length);
String s3 = new String(char[] a);
String s4 = new String(char[] a,int starIndex,int count);
String的实例化方式
//通过字面量定义的方式:此时的s1和s2的数据javaEE声明在方法区的字符串常量池中
String s1 = "javaEE";
String s2 = "javaEE";
//通过new + 构造器的方式:此时s3和s4保存的地址值,是数据在堆空间开辟空间对应的地址值,但value属性的地址与javaEE字符串常量池中的地址相同
String s3 = new String("javaEE");
String s4 = new String("javaEE");
System.out.println(s1 == s2);//true
System.out.println(s1 == s3);//flase
System.out.println(s1 == s4);//flase
System.out.println(s3 == s4);//flase
面试题:
String s = new String("abc");方式创建对象,在内存中创建了几个对象?
答:两个。一个是堆空间new结构,另一个是char[]对应的常量池数据"abc"。
String不同拼接操作的对比
结论:
-
常量与常量的拼接结果在常量池,且常量池不会存在相同内容的常量
-
只要其中有一个是变量,结果的地址就在堆中
-
如果拼接的结果调用intern()方法,返回值就在常量池中
一道面试题
public class StringTest{
String str = new String("good");//*****String具有不可变性
char[] ch = {'t','e','s','t'};
public void change(String str,char cha[]){
str = "test ok";
ch[0] = 'b';
}
public static void main(String[] args){
StringTest ex = new StringTest();
ex.change(ex.str,ex.ch);
System.out.println(ex.str);//good
System.out.println(ex.ch);//best
}
}
String,StringBuffer,StringBuilder三者的异同?
-
String:不可变的字符序列;底层使用char[]存储
-
StringBuffer:可变的字符序列;线程安全,效率低;底层使用char[]存储
-
StringBuilder:可变的字符序列;jdk5.0新增的,线程不安全,效率高;底层使用char[]存储(一般多线程情况下使用)
源码分析
String str = new String();//char[] value = new char[0];
String str1 = new String("abc");//char value = new char[]{'a','b','c'};
StringBuffer sb1 = new StringBuffer();//char[] value = new char[16];底层创建了一个长度是16的数组
System.out.println(sb1.length());
sb1.append('a');//value[0] = 'a';
sb1.append('b');//value[1] = 'b';
StringBuffer sb2 = new StringBuffer("abc");//char[] value = new char["abc".length+16];
//问题一 System.out.println(sb2.length());//3
//问题二 扩容问题:如果要添加的数据底层数组盛不了,那就需要扩容底层的数组。默认情况下,扩容为原来容量的2倍+2,同时将原有的数组的元素复制到另一个数组
- int length();//返回字符串长度:return value.length
- char charAt(int index);//返回某索引处的字符 return value[index]
- boolean isEmpty();//判断是否是空字符串 return value.length == 0;
- String toLowerCase();//使用默认环境语言,将String中所有字符转换成小写
- String toUpperCase();//使用默认环境语言,将String中所有字符转换成大写
- String trim();//返回字符串的副本,忽略前导空白和尾部空白
- boolean equal(Object obj);//比较字符串内容是否相同
- boolean equalIgnoreCase(String anotherString);//比较字符串内容是否相同,忽略大小写
- String concat(String str);//将指定字符串连接到此字符串结尾,等价于“+”
- int compareTo(String anotherString);//比较两个字符串大小
- String substring(int beginIndex);//返回一个新的字符串,它是此字符串的从beginIndex开始截取到最后一个子字符串
- String substring(int beginIndex,int endIndex);返回一个新的字符串,它是此字符串的从beginIndex开始截取到endindex(不包括)的一个子字符串
浙公网安备 33010602011771号