使用双引号,"abdcfg"、"a",双引号当中包含若干的字符,双引号当中包含一个字符也属于字符串。
使用单引号,'a'、'博',单引号里面只能包含一个字符,或者是一个汉字。
在Java当中,没有所谓的,字符串以\0结尾。
String类被final修饰是不能被继承的。
我们点开String类看源码:
标红的两个字段我们要注意一下,对于字符串来说:有两个字段一个是value[]数组,一个是hash,当我们new一个String对象,这个对象成员实际上有两部分,value引用,和一个int hash。
public class TestDemo1 {
public static void main(String[] args) {
//常见的构造String的三种方式
String str = "abcdef";
String str2 = new String("hello");//调用构造方法进行构造对象
char[] chars = {'a','b','c'};
String str3 = new String(chars);
System.out.println(str3);//把数组变成字符串
}
}
public class TestDemo1 {
public static void main(String[] args) {
String str = "abcdef";
String str2 = str;
System.out.println(str);
System.out.println(str2);
}
打印结果:
此时让Str等于bit:
public class TestDemo1 {
public static void main(String[] args) {
String str = "abcdef";
String str2 = str;
System.out.println(str);
System.out.println(str2);
str = "bit";
System.out.println("===========");
System.out.println(str);
System.out.println(str2);
}
打印结果:
注意问题:
既然Str和Str2都指向"abcdef"
是否可以通过Str2修改"acdef"->为"gbcdef"
答案是做不到!!!
因为双引号引起来的其实是一个字面值常量,常量不能被修改。
再来看一个例子:
public static void func(String s,char[] array){
s = "hanzi";
array[0] = 'e';
}
public static void main(String[] args) {
String str = "abcdef";
char[] chars = {'a','d','c','d'};
func(str,chars);
System.out.println(str);
System.out.println(chars);
}
画图分析:
所以打印结果:
提出问题:比较字符串相等不相等
ublic static void main(String[] args) {
String str1 = "hello";
String str2 = new String("hello");
System.out.println(str1==str2);
}
首先可以用等号来比较,但是我们要知道通过等号比较的是什么,是不是str1这个引用里面的地址和str2这个引用里面的地址作比较,也就是说这个过程中它比较的不是内容,比较的是里面的地址一样不一样。
打印结果:
答案:不一样
我们要清楚这个不一样,逻辑是怎么来的。
分析:
首先,双引号引起来的,会存放在到常量池里面
什么是池:池是编程中的一种常见的,重要的提升效率的方式,我们会在未来的学习中遇到各种"内存池","线程池","数据库连接池"......意义:提高效率
字符串常量池从JDK1.8开始,实际就是一个哈希表,放在了堆里面。也就是说堆里面会维护一张哈希表,在哈希表里面来存储字符串常量
什么是哈希表:数据结构-》描述和组织数据的一种方式
str2又new了一个"hello",那么此时又会生成一个"hello"对象,但是这个时候呢,当你再去常量池里面去存一个hello对象的时候,它会去常量池里面去检查有没有"hello"对象,一检查发现常量池里面有一个"hello"对象,那么又生成的这个对象就不会在常量池里面再存储一份了。
本质上str1只产生了1个对象,str2产生了2个对象,1个是常量池的"hello"对象,再1个本身new了一个对象,也属于一个对象。
所以str1==str2运行后的结果一定是一个false。
再看其他情况:
public static void main(String[] args) {
String str1 = "hello";
String str2 = "he"+"llo";//此时它俩都是常量,在编译的时候,就已经确定好了是hello
System.out.println(str1==str2);
}
打印结果:
public static void main(String[] args) {
String str1 = "hello";
String str3 = "he";
String str4 = str3+"llo";//此时str3是一个变量,编译的时候不知道是什么
System.out.println(str1==str4);
}
打印结果:
public static void main(String[] args) {
String str1 = "11";
String str2 = new String("1")+new String("1");
System.out.println(str1==str2);
}
打印结果:
intern()方法:
public static void main(String[] args) {
String str2 = new String("1")+new String("1");
str2.intern();//手动入池,当字符串常量池,没有的时候,就会入池
String str1 = "11";
System.out.println(str1==str2);
}
打印结果:
画图分析: