老问题 
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个对象的就歇歇吧

解决方案 »

  1.   

    //intern运行过程是这样的:首先查看strings pool   
    //有没“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.还不明白的话,请把引用换成指针再去读你粘的那几句话。
      

  2.   

    果然是不朽的问题
    通过反编译来看看吧
    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"就已经被编译为常量池的信息,所以类加载的时候,它就生成了。所以这个地方有争议。就看从哪个角度来看问题。
      

  3.   

    Java版的大大们谁给写个贴然后版主置顶吧 真是无语了1. 常量池、堆、栈问题
    2. 方法调用传值传引用问题
    3. == 和 .equals 问题
    4. null== 还是 ==null 的 脑残问题
    5. 楼下补充排名不分先后
      

  4.   

    String 类的intern方法 本来就是这样 这是API里的 没什么可质疑的
    人家说的是 使用NEW 方法的时候 会不会主动调用 intern方法的事
    可笑么? 有什么可笑的?
    String 类中的 public String(String original)构造方法里面 也没有调用intern方法的迹象
    提出问题就是解决的 有本事就解答清楚 你自己去搜搜网上这方面的资料 
    人家提出来 总不至于是闲的没事了 瞎说着玩 动不动就可笑 真有意思了
     
      

  5.   

    知道存放的位置就知道为什么是false
      

  6.   

    如果api文档和反汇编都解决不了您的nb问题的话,那我对您无话可说。如果你是真心来问问题的话,请解释你帖子的最后一句话。另外,对就是对,错就是错,可笑就是可笑,如果我的结论是错的,你尽可以批评,但是你要是想没事找茬的话,请你移步百度贴吧之类的地方。