本帖最后由 mqslll594212 于 2012-08-20 21:46:15 编辑

解决方案 »

  1.   

    楼主先new String(),再直接给String变量赋值试试,这样如果还是new快的话我就不知道为什么了。但我觉的此时80%可能是String快了,应为涉及到在堆的字符串池里查询和创建“12345678901”对象的过程,所以会比较慢。
    以上个人觉得
      

  2.   

    因为String str = "abc";他是先找常量池有没abc的引用,有的话就直接将str指向该地址。
    楼主说看到时间会比较短,我这里实在看不出来,我循环了100000000,楼主可以看下执行结果的区别import java.io.BufferedWriter;
    import java.io.File;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.Writer;
    import java.util.ArrayList;
    import java.util.List;/**
     * @ClassName: Test1
     * @Description: TODO(这里用一句话描述这个类的作用)
     * @author chenjw
     * @date 2012-7-16 下午5:38:28
     */public  class Test1 {
    public static void main(String args[]) throws IOException{
    long start = System.currentTimeMillis();
    String str;
    for(int i=0;i<100000000;i++){
    str = new String("abc");
    }
    long end = System.currentTimeMillis();
    System.out.println("new String,it takes " + (end - start));

    start = System.currentTimeMillis();
    String str1 ;
    for(int i=0;i<100000000;i++){
    str1 = "abc";
    }
    end = System.currentTimeMillis();
    System.out.println("it takes " + (end - start));

    start = System.currentTimeMillis();
    String str2 ;
    for(int i=0;i<100000000;i++){
    str2 = "abc";
    }
    end = System.currentTimeMillis();
    System.out.println("it takes " + (end - start));
    }
    }运行结果:
    new String,it takes 1201
    it takes 35
    it takes 35
      

  3.   

    楼主的程序中第一次执行语句String s1="12345678901";时,程序会在堆的字符串池中寻找有无“12345678901”,如有那么将其引用给s1,由于是第一次执行,所以肯定没有,那就要现在堆中创建“12345678901”对象,然后将其引用给s1,当执行到String s2=new String("12345678902");时还是查询堆中有无“12345678901”,由于上面已经创建,所以直接在栈中给s2分配内存,并使其与堆中的“12345678901”对象等值。无论那个语句在前面,在前面的语句都比下一条语句多了一个在堆中创建“12345678901”对象的过程,所以在前面的语句执行时间更长。
      

  4.   

    楼主主要时间花费在了system.out.println();其他的时间和这个比起来都是小巫见大巫,所以非常不准
      

  5.   

    String s1 = "12345678901"
    执行步骤:
    1. String 内存块中查找 对象,不存在则创建
    2. s1 指向 内存块中的地址String s1 = new String("12345678901")
    执行步骤:
    1. String 内存块中查找 对象,不存在则创建
    2. 拷贝对象值,堆中开辟一块空间并赋予值
    3. s1 指向堆中地址
      

  6.   

    String s1 = new String("12345678901")
    其实创建了俩对象。
      

  7.   

    能说的再详细吗?第一个是new的String对象,第二个是字符串常量池中的12345678901对象吗?
      

  8.   

    看时机  new会在堆里创建引用; 频繁会创建太多引用
            赋值会在池中创建新的字符串;频繁赋值建议用StringBuffer
      

  9.   

    呵呵 你都看到了 自己写的代码,new的话用了1201ms,直接赋值用了35ms,不要小看这微弱的差距哦。那你知道我那个程序是什么原因吗?前后颠倒了顺序,话费的时间不一样!
      

  10.   

    难道String s="123"也要先在堆里new一个对象??
      

  11.   

    其实这原理,大多数人都说到了。但有些人的结果出人意料。这还有几个原因:
    1.电脑的配置性能
    2.添加了System.out.println();方法会影响结果。
    ------------------------------------------------
    public static void main(String[] args) {
    // TODO Auto-generated method stub

    long time1=System.currentTimeMillis();
    for(int i=1;i<1000000;i++){
    String a=new String("123456");
    }
    long time2=System.currentTimeMillis();
    System.out.println(time2-time1);

    for(int i=1;i<1000000;i++){
    String a= "123456";
    }
    System.out.println(System.currentTimeMillis()-time2);
    }
    ---------------------------------------
    运行结果:
    39
    1
      

  12.   

    1.直接赋值:String s = "1234567890";
    2.new对象: String s = new String("1234567890");如果你需要大量的使用s,那么请使用第一种方式。因为第一种方式中"1234567890"  该字符串在方法区的常量池里面,每次取s都是取得这个常量,你可以通过String s1 = "1234567890";String s2 = "1234567890";s1==s2来看看结果,结果是true。而第二种方式,他产生的"1234567890"字符串 是在堆中生成,并且每new一次,都会分配一块新的内存来保存该字符串。虽然占用的内存不多,但是大量的话就不太好。所以从效率方面看,大量使用同一个字符串的话肯定是第一种方法好,因为他用的是同一个常量池里面的字符串。
      

  13.   

    那你还是支持我的结论?还是认为终归是new的方式会多出一步去创建堆中的对象?
      

  14.   

    我在附加一句吧,拿3楼的例子来说,大量的new,会产生大量的无用的对象,众所周知,java是自己清理垃圾的,当年轻代的空间不足,或者年老带不足,会引发GC活着FGC,而GC和FGC都是需要时间的,尤其是FGC会耗费大量的时间。所以不能疯狂的new。如果经常使用一个字符串,那就定义成常量,每次都是使用同一份。就如这样String s = "1234567890";或者定义一个static final String。
      

  15.   

    强烈建议楼主 看看 jvm的书籍,他对java内存管理有比较详细的介绍,对你理解这个问题,非常有帮助。
    http://www.amazon.cn/%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3Java%E8%99%9A%E6%8B%9F%E6%9C%BA-JVM%E9%AB%98%E7%BA%A7%E7%89%B9%E6%80%A7%E4%B8%8E%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5-%E5%91%A8%E5%BF%97%E6%98%8E/dp/B0058FLC22/ref=sr_1_1?ie=UTF8&qid=1345562786&sr=8-1
    我不是推销的,但是觉得这本书真的非常不错,讲的也通俗易懂,如果楼主想搞java的话时必备的,我这几天在第二遍翻这本书。确实不错的
      

  16.   

    什么是FGC()呢?我没查到呢,能再详细点吗?多谢!
      

  17.   


    我全是上面推荐的那本书上看的。很多虚拟机例如HOT SPOT把整个堆空间分成年轻代和年老带,看名字就很好理解,年轻代就是存一些新创建的对象,而年老带就是放一些实用了很久了但是还在用的对象。当年轻代的快满时会进行GC 也叫YoungGC,这个处理会把年轻代里面一些没有用的对象给清理掉。然后年轻代里的一部分对象满足一定条件的时候会移动到年老代,这样年老代也会不断增大,当增大到一定程度就会触发FGC,这个耗费时间相比YGC会大好几十倍。因为会同时清理年轻代和年老代,把没用的对象给清理掉。
      

  18.   

    我再发表下个人见解,如有异议,欢迎指教!
    方式一:String s1="123";   只开辟了一块内存保存“123”,变量s1指向那块物理地址。
    方式二:
    String s2=new String("123");步骤。
      1.跟上面的一步是一样的。
      2.new 对象时有开辟了一块内存,同时把“123”也复制过来。最终变量s2指向是第二块内存的物理地址。
      

  19.   

    为什么 CSDN 的讨论这种问题会这么起劲?
      

  20.   

    不管是给String类型赋值 还是new String  都是先在常量池里寻找 如果常量池里有则不再创建直接引用