老问题
String s =new String("abc");池中到底有没有 “abc”比如1 String s = new String("abc");
2 String a = "abc";结果肯定为false;有一种答案认为 1会在 堆中创建1个对象 然后去看池 发现池中没有“abc” 然后将“abc”添加到池中
所以运行2 的时候 先去搜索池 发现池中有“abc” 所以返回地址 1的引用指向堆中的对象 2中的引用指向池中的对象但是 网上搜资料有原理2:
Java中,只要使用new关键字来创建对象,则一定会(在堆区或栈区)创建一个新的对象。(jvm会马上在heap中创建一个String对象,然后将该对象的引用返回给用户。使用这种方法创建对象时,jvm是不会主动把该对象放到strings pool里面的,除非程序调用 String的intern方法。)
//例子1
String str1 = new String("abc");
//jvm 在堆上创建一个String对象
String str2 = "abc";
//jvm 在strings pool中找不到值为“abc”的字符串,因此
//在堆上创建一个String对象,并将该对象的引用加入至strings pool中
//此时堆上有两个String对象 //例子2
String str11 = new String("abc"); //jvm 在堆上创建一个String对象
str11 = str11.intern();
//程序显式将str1放到strings pool中,intern运行过程是这样的:首先查看strings pool
//有没“abc”对象的引用,没有,则在堆中新建一个对象,然后将新对象的引用加入至
strings pool中。执行完该语句后,str1原来指向的String对象已经成为垃圾对象了,随时会被GC收集。
//此时,jvm发现strings pool中已有“abc”对象了,因为“abc”equels “abc”
//因此直接返回str1指向的对象给str2,也就是说str2和str1引用着同一个对象,
//此时,堆上的有效对象只有一个。
String str22 = "abc";
if(str11 == str22){
System.out.println("str11 == str22");
}else{
System.out.println("str11 != str22");
}
//打印结果是 str11 == str22 希望高手解答
另外 引用不叫对象 说什么生成3个 5个对象的就歇歇吧
String s =new String("abc");池中到底有没有 “abc”比如1 String s = new String("abc");
2 String a = "abc";结果肯定为false;有一种答案认为 1会在 堆中创建1个对象 然后去看池 发现池中没有“abc” 然后将“abc”添加到池中
所以运行2 的时候 先去搜索池 发现池中有“abc” 所以返回地址 1的引用指向堆中的对象 2中的引用指向池中的对象但是 网上搜资料有原理2:
Java中,只要使用new关键字来创建对象,则一定会(在堆区或栈区)创建一个新的对象。(jvm会马上在heap中创建一个String对象,然后将该对象的引用返回给用户。使用这种方法创建对象时,jvm是不会主动把该对象放到strings pool里面的,除非程序调用 String的intern方法。)
//例子1
String str1 = new String("abc");
//jvm 在堆上创建一个String对象
String str2 = "abc";
//jvm 在strings pool中找不到值为“abc”的字符串,因此
//在堆上创建一个String对象,并将该对象的引用加入至strings pool中
//此时堆上有两个String对象 //例子2
String str11 = new String("abc"); //jvm 在堆上创建一个String对象
str11 = str11.intern();
//程序显式将str1放到strings pool中,intern运行过程是这样的:首先查看strings pool
//有没“abc”对象的引用,没有,则在堆中新建一个对象,然后将新对象的引用加入至
strings pool中。执行完该语句后,str1原来指向的String对象已经成为垃圾对象了,随时会被GC收集。
//此时,jvm发现strings pool中已有“abc”对象了,因为“abc”equels “abc”
//因此直接返回str1指向的对象给str2,也就是说str2和str1引用着同一个对象,
//此时,堆上的有效对象只有一个。
String str22 = "abc";
if(str11 == str22){
System.out.println("str11 == str22");
}else{
System.out.println("str11 != str22");
}
//打印结果是 str11 == str22 希望高手解答
另外 引用不叫对象 说什么生成3个 5个对象的就歇歇吧
//有没“abc”对象的引用,没有,则在堆中新建一个对象,然后将新对象的引用加入至
//strings pool中。不知道你例2里面这三行话是从哪粘的,例2只能补充说明例1的结论是对的,而不能池中放引用这个可笑的结论,请仔细读读API文档先。When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned. Otherwise, this String object is added to the pool and a reference to this String object is returned.还不明白的话,请把引用换成指针再去读你粘的那几句话。
通过反编译来看看吧
public class StringTest {
public static void main(String[] args) {
new String("abc");
}
}
javac StringTest.java //编译
javap -verbose StringTest //反编译反编译结果
D:\Test>javap -verbose StringTest
Compiled from "StringTest.java"
public class StringTest extends java.lang.Object
SourceFile: "StringTest.java"
minor version: 0
major version: 50
Constant pool:
const #1 = Method #6.#15; // java/lang/Object."<init>":()V
const #2 = class #16; // java/lang/String
const #3 = String #17; // abc
const #4 = Method #2.#18; // java/lang/String."<init>":(Ljava/lang/String
;)V
const #5 = class #19; // StringTest
const #6 = class #20; // java/lang/Object
const #7 = Asciz <init>;
const #8 = Asciz ()V;
const #9 = Asciz Code;
const #10 = Asciz LineNumberTable;
const #11 = Asciz main;
const #12 = Asciz ([Ljava/lang/String;)V;
const #13 = Asciz SourceFile;
const #14 = Asciz StringTest.java;
const #15 = NameAndType #7:#8;// "<init>":()V
const #16 = Asciz java/lang/String;
const #17 = Asciz abc;
const #18 = NameAndType #7:#21;// "<init>":(Ljava/lang/String;)V
const #19 = Asciz StringTest;
const #20 = Asciz java/lang/Object;
const #21 = Asciz (Ljava/lang/String;)V;{
public StringTest();
Code:
Stack=1, Locals=1, Args_size=1
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 1: 0
public static void main(java.lang.String[]);
Code:
Stack=3, Locals=1, Args_size=1
0: new #2; //class java/lang/String
3: dup
4: ldc #3; //String abc
6: invokespecial #4; //Method java/lang/String."<init>":(Ljava/lang/Strin
g;)V
9: pop
10: return
LineNumberTable:
line 3: 0
line 4: 10
}通过反编译代码可以看出,常量池存在abc (红色地方)
再看代码执行蓝色地方
代码执行过程,先执行new指令,在堆中分配内存,并对象的内存地址压栈
再执行dup指令,把new出来的对象的地址复制一份压入栈顶
然后ldc指令,从常量池入口查找"abc"对象,并把它压入操作数栈
接着invokespecial,就是用ldc找到的"abc"对象初始化dup指令压栈的对象地址
pop,这里因为是没有变量引用对象,所以new时压栈的对象的内存地址出栈
最后return,程序结束好了,来看看,到底有几个对象(注意是有几个,而不是生成几个),首先常量池中一个"abc",然后是堆中new出来的一个,所以是2个。
那么常量池的"abc"算不算是代码执行时生成的呢,有人说算,有人说不算,说算,是因为如果没有这条代码,常量池就不会存在"abc",也就说常量池就不会创建"abc",说不算,是因为"abc"在代码执行前就被创建了,也就是java被编译生成字节码时,"abc"就已经被编译为常量池的信息,所以类加载的时候,它就生成了。所以这个地方有争议。就看从哪个角度来看问题。
2. 方法调用传值传引用问题
3. == 和 .equals 问题
4. null== 还是 ==null 的 脑残问题
5. 楼下补充排名不分先后
人家说的是 使用NEW 方法的时候 会不会主动调用 intern方法的事
可笑么? 有什么可笑的?
String 类中的 public String(String original)构造方法里面 也没有调用intern方法的迹象
提出问题就是解决的 有本事就解答清楚 你自己去搜搜网上这方面的资料
人家提出来 总不至于是闲的没事了 瞎说着玩 动不动就可笑 真有意思了