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是引用数据类型,当
String str1="Hello";
String str2=str1;
代表
修改str2指向的字符串,str1的字符串内容会变吗?
String str1="Hello";
String str2=str1;
str2="Java"
System.out.println(str1); //Hello
System.out.println(str2); //Java
显然不能,直接赋值字符串,只是改变了str2中保存的地址,str1所指向的字符串并无变化;
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
如果现在采用了直接赋值的模式进行String类的对象实例化操作,那么该实例化对象(字符串内容)将自动保存到这个对象池之中.
(1)如果下次继续使用直接赋值的模式声明String类对象,此时对象池之中如若有指定内容,将直接进行引用
(2)如若没有,则开辟新的字符串对象而后将其保存在对象池之中以供下次使用
1.
String str1="hello";
String str2="hello";
String str1=new String("Hello Java");
这样创建的缺点:
(1)会开辟两个内存空间,其中一个会被jvm回收掉
(2)字符串不共享,浪费空间
解决空间浪费的问题:
使用intern方法,将string对象加入到字符串常量池中;
String str1 = new String("hello").intern() ;
1.直接构造:只会开辟一块内存空间,并且该字符串对象可以自动保存在对象池中供下次使用
2.构造方法:会开辟两块堆内存空间,不会自动保存在对象池中,可以使用intern()手工入池。
String str = "hello" ;
str = str + " world" ;
str += "!!!" ;
System.out.println(str)//hello world!!!
因为在源码中,String被final修饰,所以不可变;
此处代码只是利用,+=生成了新的字符串,str引用了新的字符串
1.借助原字符串,创建新的字符串。
2.反射
1.方便实现字符串线程池
2.不可变对象是线程安全的
3.不可变对象方便缓存hash code,作为key时,可以更高效的保存到Map中