关于字符串常量池实在有个地方想不明白,求大神指点!

达达萌萌哒 2019-05-07 12:38:08
如图所示,Java书里说语句String str = new String("hello"); 会在堆内存中创造两个堆内存空间,除了new出来的那块堆内存,定义字符串常量的堆内存空间是属于没有栈内存引用的垃圾,会被回收。可是我看好多资料里说使用构造方法实例化String对象时候,除了new出来的那个堆内存中的对象,另外一个字符串匿名对象会被保存在字符串常量池中,那这个对象按书里的说法就是垃圾会被gc呀。 举例: String s3 = new String("1") + new String("1"); 表达式第一个操作数我懂,就是开辟了两个对象,一个new出来的堆对象,一个对象放在了字符串常量池里,那么第二个new String("1")也要在堆内存中new一个新对象我懂,我不明白的是第二个操作数,但我看网上说这时候字符串常量池里有1这个对象了,就不需要在开辟一个对象了。我就是在这里想不通,通过第一个new String("1")而在字符串常量池中开辟的对象不算是没有任何栈指向的垃圾么???要是垃圾的话,那么这个匿名对象在第二个new String("1")之前就被gc回收了话怎么办呢?
...全文
416 11 打赏 收藏 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
专业路人甲 2019-12-06
  • 打赏
  • 举报
回复
理解错了new不会自己加入字符串池,只有String xx = “xxx”这种才会
weixin_40599844 2019-12-06
  • 打赏
  • 举报
回复
理解错了new不会自己加入字符串池,只有String xx = “xxx”这种才会
达达萌萌哒 2019-05-08
  • 打赏
  • 举报
回复
引用 6 楼 qq_39936465的回复:
[quote=引用 5 楼 达达萌萌哒 的回复:]
[quote=引用 3 楼 qq_39936465的回复:]String str = new String(“hello") str指向内存栈中hello的存储的地址

String str = new String(“hello").intern(); 把str 指向 常量池中hello的地址。如果常量池中不存在hello这个常量就生产hello这个常量,并将str指向该地址。

public class StringDemo{
public static void main(String[] args){
Book bk = new Book();
bk.test():
// 请问执行这里的时候,是不是由Book类在字符串常量池里之前存的hello有可能已经被回收了呢?
String str = new String("hello");
}
}
class Book{
public void test{
System.out.println("hello".equals("hello"))
}
}[/quote]

确实有可能执行完test();就被回收了。具体过程需要学习jvm机制这类知识。[/quote] 嗯嗯,谢谢大神,大神辛苦了,我还是个菜鸟,等我看完手上这本Java基础语法书,我就去找大神说的书看。那大神我还有两个问题哦,劳烦你了 第一个:如果这个String str = new String(“hello") 语句是写在某个类的某个方法中的,那它就是个局部变量,那它的作用域就是与方法共存亡(这是菜鸟教程里说的),那么这个方法结束后,但类没结束,这时候由这个语句在字符串常量池里保存的hello会被回收么? 第二个:String str = new String(“hello").intern(),这句话是不是很没有意义啊,因为就算不把这个str入池,在String str = new String(“hello")的时候也会保存一个hello到字符串常量池中的。
qq_39936465 2019-05-08
  • 打赏
  • 举报
回复
引用 5 楼 达达萌萌哒 的回复:
[quote=引用 3 楼 qq_39936465的回复:]String str = new String(“hello") str指向内存栈中hello的存储的地址

String str = new String(“hello").intern(); 把str 指向 常量池中hello的地址。如果常量池中不存在hello这个常量就生产hello这个常量,并将str指向该地址。

public class StringDemo{
public static void main(String[] args){
Book bk = new Book();
bk.test():
// 请问执行这里的时候,是不是由Book类在字符串常量池里之前存的hello有可能已经被回收了呢?
String str = new String("hello");
}
}
class Book{
public void test{
System.out.println("hello".equals("hello"))
}
}[/quote]

确实有可能执行完test();就被回收了。具体过程需要学习jvm机制这类知识。
哦呼 2019-05-08
  • 打赏
  • 举报
回复
这个 String.intern() 分为JDK1.6和1.7以后的区别的
如果在jdk1.6,那么就将堆中的"str01"添加到常量池中,如果是jdk1.7,那么就在常量池保存指向堆中"str01"的地址。
String str = new String("str");
str.intern();检查到常量池不存在"str01",如果在jdk1.6,那么就将堆中的"str"添加到常量池中,如果是jdk1.7,那么就在常量池保存指向堆中"str"的地址。
达达萌萌哒 2019-05-08
  • 打赏
  • 举报
回复
引用 3 楼 qq_39936465的回复:
String str = new String(“hello") str指向内存栈中hello的存储的地址

String str = new String(“hello").intern(); 把str 指向 常量池中hello的地址。如果常量池中不存在hello这个常量就生产hello这个常量,并将str指向该地址。
public class StringDemo{ public static void main(String[] args){ Book bk = new Book(); bk.test(): // 请问执行这里的时候,是不是由Book类在字符串常量池里之前存的hello有可能已经被回收了呢? String str = new String("hello"); } } class Book{ public void test{ System.out.println("hello".equals("hello")) } }
达达萌萌哒 2019-05-08
  • 打赏
  • 举报
回复
引用 2 楼 qq_39936465的回复:
[quote=引用 1 楼 达达萌萌哒 的回复:]
我就是很不明白,我看的书也好,网上的资料也好,一会儿说这个"hello"这个字符串是匿名对象会被保存在字符串常量池里,可以供下次重复使用,一会儿又会说这个String类的匿名对象是垃圾,正在等待被gc会被回收。都被回收了还这么重复使用呢?书里还说String str = new String(“hello").intern();
这样是将new出来的对象入池,可是在执行String str = new String(“hello")的时候已经在字符串常量池里保存了一个hello对象呀,再执行如此入池操作,那么字符串常量池里会有两块内存里存的内容都是hello么???
这里真是搞糊涂了


应该说在该类结束之前你不用担心被当垃圾回收问题,只有该类结束了gc才会回收常量池中的垃圾。
[/quote] 谢谢大神的指点但我还是有点不明白,在类结束之前不会被回收的话,那么如果在类A里往字符串常量池里加了一个"hello",那么在另外一个类B里执行语句String str = new String(“hello"),这时候就有可能之前的字符串常量池中的hello已经被回收了对么?
qq_39936465 2019-05-08
  • 打赏
  • 举报
回复
引用 7 楼 达达萌萌哒 的回复:
嗯嗯,谢谢大神,大神辛苦了,我还是个菜鸟,等我看完手上这本Java基础语法书,我就去找大神说的书看。那大神我还有两个问题哦,劳烦你了 第一个:如果这个String str = new String(“hello") 语句是写在某个类的某个方法中的,那它就是个局部变量,那它的作用域就是与方法共存亡(这是菜鸟教程里说的),那么这个方法结束后,但类没结束,这时候由这个语句在字符串常量池里保存的hello会被回收么? 第二个:String str = new String(“hello").intern(),这句话是不是很没有意义啊,因为就算不把这个str入池,在String str = new String(“hello")的时候也会保存一个hello到字符串常量池中的。
可以看一段程序加深理解

public class test16 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		String str1 = new String("hello");
		String str2 = new String("hello").intern();
		String str3 = "hello";
		System.out.println(str1 == str2);
		System.out.println(str2 == str3);
		System.out.println(str1 == str3);

	}

}
运行结果:

false
true
false
因为String str = new String("hello"); str的指向是内存栈中的hello存储地址,字符串常量池中产生的hello是过程量,随时可以能被jvm回收。而String str = new String("hello").intern(); str被指向常量池中的hello地址等价于String str = "hello"; 这个我在3楼时已经说过了,所以2者还是有区别的。
达达萌萌哒 2019-05-07
  • 打赏
  • 举报
回复
我就是很不明白,我看的书也好,网上的资料也好,一会儿说这个"hello"这个字符串是匿名对象会被保存在字符串常量池里,可以供下次重复使用,一会儿又会说这个String类的匿名对象是垃圾,正在等待被gc会被回收。都被回收了还这么重复使用呢?书里还说String str = new String(“hello").intern(); 这样是将new出来的对象入池,可是在执行String str = new String(“hello")的时候已经在字符串常量池里保存了一个hello对象呀,再执行如此入池操作,那么字符串常量池里会有两块内存里存的内容都是hello么??? 这里真是搞糊涂了
qq_39936465 2019-05-07
  • 打赏
  • 举报
回复
String str = new String(“hello") str指向内存栈中hello的存储的地址

String str = new String(“hello").intern(); 把str 指向 常量池中hello的地址。如果常量池中不存在hello这个常量就生产hello这个常量,并将str指向该地址。
qq_39936465 2019-05-07
  • 打赏
  • 举报
回复
引用 1 楼 达达萌萌哒 的回复:
我就是很不明白,我看的书也好,网上的资料也好,一会儿说这个"hello"这个字符串是匿名对象会被保存在字符串常量池里,可以供下次重复使用,一会儿又会说这个String类的匿名对象是垃圾,正在等待被gc会被回收。都被回收了还这么重复使用呢?书里还说String str = new String(“hello").intern();
这样是将new出来的对象入池,可是在执行String str = new String(“hello")的时候已经在字符串常量池里保存了一个hello对象呀,再执行如此入池操作,那么字符串常量池里会有两块内存里存的内容都是hello么???
这里真是搞糊涂了


应该说在该类结束之前你不用担心被当垃圾回收问题,只有该类结束了gc才会回收常量池中的垃圾。

62,620

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧