String类
String类又称作不可变字符序列,位于java.lang包中,Java程序默认导入java.lang包下的所有类。Java字符串就是Unicode字符序列,例如字符串“Java”就是4个Unicode字符’J’、’a’、’v’、’a’组成的。
(注:字符串效果上是char[]字符数组,但底层原理是byte[]字节数组)
Java没有内置的字符串类型,而是在标准Java类库中提供了一个预定义的类String,每个用双引号括起来的字符串都是String类的一个实例。
String的实例化非常简单,直接双引号创界或者new String对象即可。
String str = "滑技工厂";
String str2 = new String("滑技工厂");
字符串是常量(final类),他们的值在确定后不能更改!!
(注:字符串拼接不叫更改字符串的值,拼接的本质是创建了新的字符串对象。String对象一旦被创建就是固定不变的了,对String对象的任何改变都不影响到原对象,相关的任何change操作都会生成新的对象)
字符串拼接
字符串之间通过加号**+**拼接,符号"+“把两个字符串按给定的顺序连接在一起,并且是完全按照给定的形式。当”+"运算符两侧的操作数中只要有一个是字符串(String)类型,系统会自动将另一个操作数转换为字符串然后再进行连接。
int age = 18;
String str = "age is" + age; //str赋值为"age is 18"
//这种特性通常被用在输出语句中:
System.out.println("age is" + age);
常量池
常量池分为三类:
-
全局字符串常量池(String Pool)
全局字符串常量池中存放的内容是在类加载完成后存到String Pool中的,在每个VM中只有一份,存放的是字符串常量的引用值(在堆中生成字符串对象实例)。
-
class文件常量池(Class Constant Pool)
class常量池是在编译的时候每个class都有的,在编译阶段,存放的是常量(文本字符串、final常量等)和符号引用。
-
运行时常量池(Runtime Constant Pool)
运行时常量池是在类加载完成之后,将每个class常量池中的符号引用值转存到运行时常量池中,也就是说,每个class都有一个运行时常量池,类在解析之后,将符号引用替换成直接引用,与全局常量池中的引用值保持一致。
在这里我们不深入讨论后两种。
每当我们创建一个字符串对象时,首先就会检查字符串常量池中是否存在面值相等的字符串,如果有,则不再创建,直接返回字符串常量池中对该对象的引用;若没有,则创建然后放入到字符串常量池中并且返回新建对象的引用。
(也就是说,只要出现双引号""字符串,就一定会在字符串常量池中创建一个字符串对象)
先上代码(注:对于基本数据类型,==是数值的比较;对于引用数据类型,==是地址值的比较。)
String str1 = "滑技工厂";
String str2 = "滑技工厂";
String str3 = new String("滑技工厂");
String str4 = str3.intern();
System.out.println(str1==str2);
System.out.println(str1==str3);
System.out.println(str2==str3);
System.out.println(str4==str3);
System.out.println(str4==str1);
运行结果:
为什么会出现这样的情形的?以下分析
以str1为例,创建str1存于栈中(堆栈知识在这里不展开),str1会查找字符串常量池中是否存在字符串**“滑技工厂”**,若存在,则str1引用其地址;若不存在,则先在字符串常量池中创建该字符串对象,然后引用其地址。
str2同理,因此str2与str1是同一个地址引用。
str3:在常量池中查找是否有“滑技工厂”对象,有则返回对应的引用实例,没有则创建对应的实例对象。然后在堆中new一个String(“滑技工厂”)的对象,最后str3引用堆中的这个字符串对象。
因此str3与str1、str2的地址不同,返回false。
str4是在运行的时候调用intern()函数,返回String Pool中“滑技工厂”的引用值,如果没有就将str3的引用值添加进去。
综上所述,呈现了这个结果。
因此,字符串的比较通常用str1.equals(str2)来进行,这个是字符串值的比较。
脑阔痛,如果有帮助就给个赞👍吧!!