package com.carter;
/* String 类的内存分配及原理
* String 表示一个字符串,内部使用字符数组实现,final类型 不能被继承(最终类)
*
*/
public class StringDemo {
public static void main(String[] args) {
//String的两种赋值方式,java推荐使用第一种方式
//1 直接赋值 将对象创建在堆中的字符串常量池中,通过内存地址找到该对象
String s1="123";//只创建一个对象
/*2 使用new关键字创建对象, new:表示申请内存空间 是强制型的操作,
如果发现字符串常量池中有了该对象,就会强制申请内存空间,将对象创建在堆里面
*/
/*面试题问 以下代码创建了几个对象
答: 先在字符串常量池中创建了一个对象,然后通过new关键字在堆中创建了另一个
*/
String s2=new String("123");//创建了两个对象,最少创建一个对象,有可能创建两个对象
String s3="123";/*s3直接从常量池中找对象,不需要再创建
*可以看出,第一种方法有时候不需要创建对象,重复利用
*实际上是一种内存地址的引用
*/
System.out.println(s1==s2);//判断两个对象的内存地址是否相等
System.out.println(s1==s3);//s3直接找到了常量池中的对象,
System.out.println("-------------------------------------------");
//代码示例,四种情况分析:直接赋值,字符串连接时,考虑编译期和运行期
//如果在编译期就可以被确定,那么就使用已有的对象,否则会创建新的对象
String a="a";//在编译期就可以确定a,在常量池中创建
String a1=a+1;//在编译期不会被确定,会在堆中创建新的对象a1
String a2="a1";//会在常量池中创建a2
System.out.println(a1==a2);//常量池中的a2和堆中的a1内存地址不同
final String b="b";//b为常量
String b1=b+"1";//b是常量,b1的值在编译期被确定
String b2="b1";//b2从常量池中取b1
System.out.println(b1==b2);
//用到getC方法
String c=getC();//c是通过方法得来的,方法必须通过运行期才会获得结果
String c1=c+1;//就相当于在堆中new了一个对象
String c2="c1";
System.out.println(c1==c2);
//用到getD方法
final String d=getD();//虽然是final,但是还是在运行期才会获得结果
String d1=d+1;//就相当于在堆中new了一个对象
String d2="d1";
System.out.println(d1==d2);
}
private static String getC(){
return "c";
}
private static String getD(){
return "d";
}
}