一、基本理解
节省了很多时间。常量池其实也就是一个内存空间,不同于使用new关键字创建的对象所在的堆空间。JVM为每个已加载的类型维护一个常量池,常量池就是这个类型用到的常量的一个有序集合。包括直接常量(基本类型,String)和对其他类型、方法、字段的符号引用(1)。池中的数据和数组一样通过索引访问。由于常量池包含了一个类型所有的对其他类型、方法、字段的符号引用,所以常量池在Java的动态链接中起了核心作用。常量池存在于堆中。
二、String实现常量池技术
以如下例子进行解释说明:
①
public class Test{
public static void main(String[] args){
//s1,s2分别位于堆中不同空间
String s1=new String("hello");
String s2=new String("hello");
System.out.println(s1==s2)//输出false
//s3,s4位于池中同一空间,常量池
String s3="hello";
String s4="hello";
System.out.println(s3==s4);//输出true
}
}
② String类型变量在内存中的变化
先引入代码如下:
class Demo4{
public static void main(String[] args){
String a="hello";
String b="不错";
swap(a,b);
System.out.println(a);
System.out.println(b);
}
public static void swap(String a,String b){
String temp=a;
a=b;
b=temp;
}
}
说明:String类型变量是引用数据类型变量,上面代码中变量a,b没有new新的连续的内存空间,而是存放在堆内存中的常量池中。
注:1、引用数据String类型变量在栈内存中存放的是地址,而不是具体的字符串;
2、最后输出a,b,输出结果是具体的数值,而不是相应的地址,是因为在执行输出的时候自动调用的toString()方法,将哈希码转成了相应的值。
非字符要转换成字符串类型时,一个toString()方法即可将类型进行转换。Object中的方法,所有的类中都继承了这个方法。
4、而数组类中没有对方法toString()重写。所以,数组直接使用toString()的结果也是[类型@哈希值]。所以数组转为字符串应写成:Arrays.toString(a)。
内存图如下:
三、Java把内存划分成两种:一种是栈内存,一种是堆内存。
在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配。 当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作他用。 堆内存用来存放由new创建的对象和数组。 在堆中分配的内存,由Java虚拟机的自动垃圾回收器来管理。 在堆中产生了一个数组或对象后,还可以在栈中定义一个特殊的变量,让栈中这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量。 引用变量就相当于是为数组或对象起的一个名称,以后就可以在程序中使用栈中的引用变量来访问堆中的数组或对象。