本帖最后由 linweiwen 于 2014-4-1 23:00 编辑
问题一:
你的理解没错。s1是String类创建的对象引用变量,它指向"abc"字符串。而String是final的,不能被重新赋值。
问题二:
首先,字符串常量池存在于方法区,方法区其实也是在内存中开辟了一个空间,用来放类被加载后的信息。
1.字符串常量池是在JVM中一直“静态”存在的吗?还是在每一段程序运行时才有一个字符串常量池?
首先,常量池的信息是在编译期被确定的,并被保存在编译后的.class文件(字符串常量池是常量池中的一种)。
也就是你运行javac命令后,.class文件就有了你程序中字符串常量池的信息。
因此,不能说是在JVM中一直静态存在的。
在运行java命令启动JVM前,该类的字符串常量池信息已经确定了,只是JVM启动后常量池信息被加载到内存而已。
也不是每段程序运行有一个,而是每个类有相应的常量池。JVM启动后要去维护这些被加载类的常量池。
2.字符串常量池的最初状态是空的吗?也就是说最初字符串常量池没有字符常量呢,
还是在程序运行之前已经有一些字符串常量保存在字符串常量池中了?
既然常量池是加载对应类的信息存储区,那么它的最初状态,就是根据你的代码怎么写就怎么定,你没写字符串,当然就没有东西了。
3.假设在字符串常量池没有"Hello"字符串常量,在运行String s1 = "Hello";后便有了。
那么在该程序结束后,再次运行时,字符串常量池里还有"Hello"该字符串常量吗?
这个问题,看了上面的回到就应该知道,
在编译程序后,就已经保存有Hello字符串的信息,
运行的时候,只是加载到常量池的内存空间。
程序结束后,内存中的"Hello"字符串是没有了,.class文件还保留有信息。
再次运行时,有根据这个信息创建字符串常量池,里面就有了"Hello"字符串。
4.我自己的理解是:在StringTest这个程序运行时,CPU会给这个程序分配一段内存(栈区,堆区,方法区等),而字符串常量池就存储在方法区。
每一个程序运行时都会有一个字符串常量池,但这时字符串常量池里还没有任何字符串常量。
在运行String s1 = "Hello";后便有了"Hello"字符串常量。程序结束后,字符串常量池也就不存在了。
不知道我的理解是否正确。
基本看上面,补充一下:方法区(内含常量池)在JVM启动时被创建,每个类有它自己的常量池,
它在编译完成后里面就保存有你代码中字符串常量的信息,
运行时s1便指向"Hello",而不是运行时才有,是s1被创建后指向已经被加载到常量池中的"Hello"。
5.使用字符串常量池有一个好处,就是在有多个引用都指向“Hello”字符串常量时,可以直接拿来使用,不用再另外给这些引用创建多个“Hello”字符串对象。这样节约了内存的使用。感觉这样子的话,使用String s1 = "Hello";完全可以实现String s1 = new String("Hello");的功能。既然Java有String s1 = new String("Hello");这样的语法,那么它肯定有什么作用是用String s1 = "Hello";实现不了的。那么是什么呢?
这个问题实在回答不了,个人感觉没这么复杂,两种方式其实要根据实际需要决定用那个,
看你第三个问题就有这种情况了。
三、关于比较两个字符串是否相等
s3、s4的地址不一样,所以不能用"==",但其实它们都是指向同一个“Hello”,内容一样。
Java就提供了equals这个方法解决了。
|