飞沐网站建设公司北京/百度指数搜索指数的数据来源
Java阶段一Day13
文章目录
- Java阶段一Day13
- String字符串类型
- 图文讲解
- 小练习
- 拓展
API:应用程序接口 (Application Programming Interface)
是Java中已经提供好的常用的类、接口、方法等
String字符串类型
-
java.lang.String类使用
final
修饰,不能被继承java.lang包:(language)语言包,java将特别常用的类封装到 java.lang 包中,所以 java.lang 包中的类不需要
import
的,如String
、Math
-
String的底层封装的是一个字符数组
-
String在内存中采用Unicode编码格式,每个字符占2个字节的内存空间
-
Java推荐我们使用 字面量 / 直接量 ( 直接" " )的方式来创建字符串对象,并且会将所有以字面量方式创建的对象缓存到常量池(字符串常量池)中,当使用相同字面量再创建字符串对象时将会复用常量池中的对象,以减少内存开销。
-
字符串对象一旦创建,对象内容永远无法改变,但字符串引用可以重新赋值(指向新的对象)
-
String是个不变对象,其方法中有个 final char[ ],是不可变的
public final class Stringimplements java.io.Serializable, Comparable<String>, CharSequence {/** The value is used for character storage. */private final char value[];
图文讲解
使用字面量创建字符串对象,系统会首先查看字符串常量池中是否已经有该对象的地址
没有则在堆中创建对象后,并缓存到常量池中,存储该字面量对象的地址。
引用类型在栈中装的都是地址,指向堆中的对象,
当又声明同一字面量,系统同样先查看字符串常量池中是否有该对象地址,有则直接引用返回,不用再重新创建字符串对象
![]](https://img-blog.csdnimg.cn/c254f6b4be8943948b39a2cca999f855.png)
String不可变,当修改原有s1的值会新创建一个对象,s1指向新对象的地址
小练习
String s1 = "hello";//1)创建hello的字面量对象2)将其存储到字符串常量池中
String s2 = "hello";//1)直接复用常量池中的那个对象,而不会再分配
System.out.println(s1 == s2); //trueString s3 = "123abc";//堆中创建123abc字面量对象,并缓存到常量池中
//编译器在编译时,若发现是两个字面量相连,则会直接连接好并将结果保存起来
//如下语句会被编译为: String s4 = "123abc";
String s4 = "123"+ "abc"; //复用常量池中的引用
System.out.println(s3 == s4); //trueString s5 = "123";
//因为s5是一个变量,所以在编译期并不会直接编译好
s5 = s5+"abc" ;//创建一个新的对象存储123abc
System.out.println(s5 == s4); //falseString s6 = new String("hello");
/*
面试题:
17行创建了几个对象
答案:2个
第一个:字面量"hello"
---java会创建一个String对象表示字面量"hello",并将其存入常量池中
第二个:new String()
---new String() 时会再创建一个字符串对象,并引用hello的字符串内容
*/String s7 = new String("hello");
System.out.println(s6 == s7); //falseString s8 = "hello";
System.out.println(s8 == s7); //false
System.out.println(s8.equals(s7)); //trueString s9 = s7.intern();
System.out.println(s9 == s7); //false
System.out.println(s9 == s8); //true
//intern()方法表示如果字符串在池中有,就返回池中的引用,否则在池中创建一个引用,再返回该引用
关于上述练习中的面试题图像讲解:
-
第一个创建的是字面量对象
-
第二个创建的是 new 出来的String对象
-
栈中的s存储的地址是 new 出来的地址
-
栈中的s1存储的地址是字面量的地址
拓展
JVM字符串常量池会进行垃圾回收吗?
会,但是对方法区的回收“成绩”比较难以令人满意,Java虚拟机规范中确实说过可以不要求虚拟机在方法区实现垃圾回收,而字符串常量池在方法区中。
假设一个字符串"everor"已经进入了常量池,但是当前系统中没有一个String对象引用常量池中的"everor"常量(即String str = new String(“everor”);),也没有其他地方引用了这个字面量(即String str = “everor”;),如果这个时候发生了内存回收,而且有必要的话,这个"everor"常量就会被系统清理出常量池。
在HotSpot虚拟机中,方法区又被称为永久代,永久代这个概念在其它虚拟机(如BEA JRockit、IBM J9等)中是不存在的。但是使用永久代来实现方法区,并不是一个好主意,因为这样更容易遇到内存溢出问题。从JDK1.7开始,逐步使用元空间(MetaSpace)代替永久代的概念。元空间的内存大小取决于本地内存大小。元空间代替永久代,并不意味着字符串常量池就到了元空间,而是移到了堆中。