String总结2

String总结

  • String
    • 创建String的三种方式
    • 引用
    • 字符串比较相等
    • 字符串常量池
    • String类中两种实例化对象的区别
    • 字符串不可变
            • 如何修改字符串?
    • 为什么String要不可变?

String

String 也是引用类型,也是不可变的;

创建String的三种方式

    //方式一
    String str1="Hello Java";
    
    //方式二
    String str2=new String("Hello Java");
    
    //方式三
    char[] arr=new char[]{'H','e','l','l','o',' ','J','a','v','a'};
    String str3=new String(arr);

引用

类似于C语言的指针,但是不能像指针自加那么灵活,类似C++的起别名;

String str="Hello";

str是在栈中,保存的是字符串“Hello”的地址;字符串一般保存在堆中;
String总结2_第1张图片
因为String是引用数据类型,当

String str1="Hello";
String str2=str1;

代表
String总结2_第2张图片
修改str2指向的字符串,str1的字符串内容会变吗?

String str1="Hello";
String str2=str1;
str2="Java"
System.out.println(str1); //Hello
System.out.println(str2); //Java

显然不能,直接赋值字符串,只是改变了str2中保存的地址,str1所指向的字符串并无变化;
String总结2_第3张图片

字符串比较相等

String str1="Hello Java";
String str2="Hello Java";
System.out.println(str1==str2);//true
String str1=new String("Hello Java");
String str2=new String("Hello Java");
System.out.println(str1==str2); //false

代码1的内存布局类似:
String总结2_第4张图片
代码2:
String总结2_第5张图片

字符串常量池

如果现在采用了直接赋值的模式进行String类的对象实例化操作,那么该实例化对象(字符串内容)将自动保存到这个对象池之中.
(1)如果下次继续使用直接赋值的模式声明String类对象,此时对象池之中如若有指定内容,将直接进行引用
(2)如若没有,则开辟新的字符串对象而后将其保存在对象池之中以供下次使用
1.

String str1="hello";
String str2="hello";

String总结2_第6张图片
String总结2_第7张图片

String str1=new String("Hello Java");

String总结2_第8张图片
这样创建的缺点:
(1)会开辟两个内存空间,其中一个会被jvm回收掉
(2)字符串不共享,浪费空间
解决空间浪费的问题:
使用intern方法,将string对象加入到字符串常量池中;

String str1 = new String("hello").intern() ;

String类中两种实例化对象的区别

1.直接构造:只会开辟一块内存空间,并且该字符串对象可以自动保存在对象池中供下次使用
2.构造方法:会开辟两块堆内存空间,不会自动保存在对象池中,可以使用intern()手工入池。

字符串不可变

String str = "hello" ;
str = str + " world" ;
str += "!!!" ;
System.out.println(str)//hello world!!!

因为在源码中,String被final修饰,所以不可变;
此处代码只是利用,+=生成了新的字符串,str引用了新的字符串

如何修改字符串?

1.借助原字符串,创建新的字符串。
2.反射

为什么String要不可变?

1.方便实现字符串线程池
2.不可变对象是线程安全的
3.不可变对象方便缓存hash code,作为key时,可以更高效的保存到Map中

你可能感兴趣的:(JAVA,java,字符串)