java的string存放位置的疑惑
问题描述
有一道题是这样的:
new String('aaa')创建了几个对象? 答案是创建一个或2个,理由是如果常量区中存在了aaa变量,则只在堆中创建一个;如果常量区不存在aaa变量,则分别在常量区和堆中各创建一个。
但我实际测试的结果却不符:
String s1 = new String('aaa');String s2 = 'aaa';System.out.println(s1 == s2); //false
如果说new String('aaa')在堆中和常量区中都创建了对象,那么为什么s2不直接复用s1的常量池的引用呢?
补充:发现自己想错了,s1应该指向的堆中的元素,而s2指向的是常量池中的,所以两者不相等是对的,那有没有办法测试测试出new String('aaa')也同时在常量池中创建对象了呢?
又或者String s3 = 'aa'.concat('a'); 请问这个s3是指向堆中还是指向常量池的,它能否复用常量池中的变量呢?
问题解答
回答1:String s1 = new String('aaa'); String s2 = 'aaa'; System.out.println(s1 == s2); //false System.out.println(s1.intern() == s2); //true
当一个String实例调用intern()方法时,会查找常量池中是否有相同的字符串常量,如果有,则返回其的引用,如果没有,则在常量池中增加一个等于str的字符串并返回它的引用,由于s2已经在常量池中,所以s1.intern()不会再创建,而是直接引用同一个'aaa'。
如果这个还不够明显,那么我们就来试验,
public class Cons { public static void main(String[] args) throws InterruptedException {String s1 = new String('vv'); }}
然后命令行
注意常量池有 VV
回答2:问题一:String a = “aaa”,会在常量池中创建对象,如果常量池中存在同样的对象,那a就直接指向该对象。而 String a = new String('aaa'),若常量池中存在,则不在常量池中创建,只在堆中创建。
String a = new String('aaa');String b = new String('aaa');System.out.println(a == b);//比较两者堆中的引用返回falseSystem.out.println(a.intern() == b.intern());//比较两者常量池中的引用,返回true问题二:
从源码中找答案String s3 = 'aa'.concat('a'); 其实就相当于 String s3 = new String('aaa'),会在堆中创建对象。
public String concat(String str) { int otherLen = str.length(); if (otherLen == 0) {return this; } int len = value.length; char buf[] = Arrays.copyOf(value, len + otherLen); str.getChars(buf, len); return new String(buf, true);}回答3:
String不是每次赋值都重新创建一个String对象实例吗?所以才会有StringBuilder呀。
回答4:按照面向对象的思想,有没有同时在常量池创建对象,可能String自己最清楚,嗯,他有一个intern()方法。
回答5:前面几位的回答已经非常好了,我补充一句,我们经常说的“把字符串放到常量池”是指把字符串的引用放到字符串常量池(String Pool,本质是一个哈希表)中,字符串本身还是放在堆上的。
回答6:// new一次就是在堆中创建一个新的对象。不new的话aaa直接在字符串常量中取值;// String s2 = 'aaa'; 先在内存中寻找aaa,如果有,则将aaa的内存首地址指向了s1, 如果没有则在堆中中创建一个新的对象。// String s1 = new String('aaa');// // 不管'aaa'在内存中是否存在,都会在堆中开辟新空间,将字符串'aaa'的内存首地址指向s1。String a = 'aaa';// aaa在常量池中创建一个对象,将内存首地址指向了aString b = 'aaa';// 直接aaa已经存在的内存首地址指向b。String c = new String('aaa');// 不管存在与否,在堆中创建1个空间,内存首地址与常量池中的地址完全不同System.out.println(a==b);// trueSystem.out.println(a==c);// false
相关文章:
1. html5 - 百度Ueditor代码高亮和代码段滚动条冲突是怎么回事?2. javascript - vue 数据更新了。但是dom没有更新,,,,,如图3. mysql - sql 中 group 和field 查询问题。4. css3中translate(-50%,-50%)对 transform-origin的奇葩影响?5. css - 关于input标签disabled问题6. javascript - 静态页面引公共头尾文件,js怎么写吖?7. java基础,求解答。8. 老师,layui.css无法使用,路径都是按照视频照做的,是不是还有其他步骤需要做?9. 如何调整IDEA中直接运行java程序的日志输出级别?10. debian - docker依赖的aufs-tools源码哪里可以找到啊?