string类的问题

1、String的概念

String 被声明为 final,因此它不可被继承。

内部使用 char 数组存储数据,该数组被声明为 final,这意味着 value 数组初始化之后就不能再引用其它数组。并且 String 内部没有改变 value 数组的方法,因此可以保证 String 不可变。

2、String好处

1. 可以缓存 hash 值

因为 String 的 hash 值经常被使用,例如 String 用做 HashMap 的 key。不可变的特性可以使得 hash 值也不可变,因此只需要进行一次计算。

2. String Pool 的需要

如果一个 String 对象已经被创建过了,那么就会从 String Pool 中取得引用。只有 String 是不可变的,才可能使用 String Pool

3. 安全性

String 经常作为参数,String 不可变性可以保证参数不可变。例如在作为网络连接参数的情况下如果 String 是可变的,那么在网络连接过程中,String 被改变,改变 String 对象的那一方以为现在连接的是其它主机,而实际情况却不一定是。

4. 线程安全

String 不可变性天生具备线程安全,可以在多个线程中安全地使用

3、String的创建过程

jvm为了提升性能和减少内存开销,避免字符的重复创建,其维护了一块特殊的内存空间,即字符串池,当需要使用字符串时,先去字符串池中查看该字符串是否已经存在,如果存在,则可以直接使用,如果不存在,初始化,并将该字符串放入字符串常量池中。

String s1 = "aaa";程序运行时会在常量池中查找”aaa”字符串,若没有,会将”aaa”字符串放进常量池,再将其地址赋给s2;若有,将找到的”aaa”字符串的地址赋给s1。

String s2 =new String("bbb");先在堆中创建空间,里面维护了value属性(看底层源码),指向常量池空间,如果常量池没有”hello",则重新从常量池中创建,如果有,直接通过value指向常量池地址空间。(最终指向的是堆中的地址空间)。

 

创建了几个对象?
String str = "hello" + "abc";
//str编译器自动优化等价于:string str = "helloabc"
常量相加是在常量池里面

String a = "hello";
String b = "abc";
String c = a + b; //创建了几个对象?
//一共创建了几个对象?(3个)

 变量相加在堆中

4、String.intern()

使用 String.intern() 可以保证相同内容的字符串变量引用同一的内存对象

JKD1.7中:intern的处理是 先判断字符串常量是否在字符串常量池中,如果存在直接返回该常量,如果没有找到,说明该字符串常量在堆中,则处理是把堆区该对象的引用加入到字符串常量池中,以后别人拿到的是该字符串常量的引用,实际存在堆中

 

复制代码
public static void main(String[] args) {
    String s = new String("1");// 在堆中创建了String类对象,在常量池中创建了”1“
    s.intern();//字符串常量存在常量池中,直接返回”1“的地址。
    String s2 = "1";//常量池中存在"1",直接返回“1”的地址
    System.out.println(s == s2);//false s指向堆中地址,s2指向常量池中地址

    String s3 = new String("1") + new String("1");//在堆中创建了String类地址,在常量池创建了”1“,实际上s3为”11“存在于堆中。
    s3.intern();//常量池中无11,将”11”加入池中,把堆区该对象的引用加入到字符串常量池中,以后别人拿到的是该字符串常量的引用,实际存在堆中
    String s4 = "11";//拿到的是11的引用地址。
    System.out.println(s3 == s4);
}
复制代码

 

 

posted @   NOE42  阅读(28)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
点击右上角即可分享
微信分享提示