看到的一道面试题,但是我不知道(3)是哪里的。
(1)string str1 = "",(2)string str1 = null,(3)string str1 = string.Length = 0;
上面三个式子哪个运行更快?    期待高手解答。并解释清楚

解决方案 »

  1.   

    同问(3)的写法出处。
    (1)声明并建立了一个长度为0的字符串对象,分配了内存空间;(2)跟String str1一样,没有分配。
    基于Java时间的精度,看不出来谁快,但理论上应该是(2)快。
      

  2.   

       我曾经写了一个程序测试,但是每次运行的时间都不一样。不过三次(1)是最快的,不知道为什么。public class TestXiaolv { /**
     * @param args
     */
    public static void main(String[] args) {
    // TODO Auto-generated method stub
    long start = System.currentTimeMillis(); String[] s = new String[100000]; for (int i = 0; i < s.length; i++) {
    //s[i] = "";  //第一个 3078ms
    //s[i] = null;  //第二个 3125ms

    } for (String e : s) {
    System.out.println("测试时间开销:" + e);
    } long end = System.currentTimeMillis();
    System.out.println("程序执行时间:"+(end - start) + "ms"); }}
      

  3.   

    我们知道如果赋值,则引用实际存储的是一个内存地址,也就是一个整数,如果不赋值,则为null,null是一个已经定义好的常量,他的值是0,在内存地址0上是找不到任何对象的,也就是说该引用不指向任何对象。null存在静态池中.
    ""在字符串池中.
      

  4.   

    不管你信不信,几次测下来1比2快一点点,我是这么测的:public class SpeedTest { public static void main(String[] args) {
            long start;
            long end;
            
            start = System.currentTimeMillis();
            for (int i = 0; i < Integer.MAX_VALUE; i++) {
                //自己可以换成 null 试试。
                  String str1 = "";
            }
            end = System.currentTimeMillis();        
            System.out.println(end-start);
    }}
      

  5.   

    我也曾经测试过,但是一直没时间研究JVM。我目前的解释:string str1 = "" 这个只是一个引用变换,同时""在编译阶段就确定了地址,存在于JVM独有的共享池之中。将地址置换成null,就是把地址变成\u0000,可能会有地址空间检测程序。------------------------------------------------------------------------------------------------
    以上第二条是我的推测没有根据,希望研究JVM的高手给予指点。一下是本人测试代码:
    创建空字符串类:
    package com.common;public class BulidSpaceString {
    public static void bulidSpace(Integer con){   
       int i=0;
    for (i = 0; i < con.intValue(); i++) {
                 String a="";         
        }
        System.out.println(i);
    }
    }创建null类:package com.common;
    public class BuildNullString {
    public static void buildNull(Integer con){   
        int i=0;
    for (i = 0; i < con.intValue(); i++) {
               String a=null;
        }
    System.out.println(i);
        
    }
        
    }测试基类:package com.common;import java.lang.reflect.Method;
    import java.util.List;public class RunTime { /**
     * 通过方法名动态调用对象方法
     * 
     * @param clsName
     *            调用类
     * @param methodName
     *            方法名
     * @param args
     *            方法参数
     * @return
     * @throws Exception
     */
    public static long invokeStaticMethod(String clsName, String methodName,
    Object[] args) throws Exception {
    long start = System.nanoTime();
    try {
    Class c = Class.forName(clsName);
    Class[] argsClass = new Class[] {Integer.class};
    Method method = c.getMethod(methodName, argsClass);
    method.invoke(c, args);
    } catch (Exception e) {
    e.printStackTrace();
    }
    long end = System.nanoTime();
    return end - start;
    }
    }测试核心区:package com.common;import java.util.ArrayList;
    import java.util.List;public class TestSpaceForString {
    public static void main(String[] args) {
    Integer a=100000;
    Object[] param=new Object[]{a};
    try {
    long runTime=RunTime.invokeStaticMethod("com.lfpost.common.BuildNullString", "buildNull", param);
    System.out.println("采用BuildNullString转化方法执行时间"+runTime);
    long runTimeByColl=RunTime.invokeStaticMethod("com.lfpost.common.BulidSpaceString", "bulidSpace", param);
    System.out.println("采用BulidSpaceString执行时间"+runTimeByColl);
    System.out.println("微秒相差(runTimeByColl-runTime)=" +String.valueOf(runTimeByColl-runTime));
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    }-------------------------------------------------------------
    100000
    采用BuildNullString转化方法执行时间5007061
    100000
    采用BulidSpaceString执行时间3681474
    微秒相差(runTimeByColl-runTime)=-1325587说白了是String abc="" 快一些!可能我这么测试不合理大家指正!
      

  6.   

    如果是考(1)string str1 = "";(2)string str1 = new String(""); 谁快,那才有点意义。
      

  7.   

    我觉得这种测法是不是会受到以下代码的影响啊
    for (String e : s) {
    System.out.println("测试时间开销:"+ e);
    感觉把这段代码去掉好象是2比较快一些
    我在机器上测试的代码如下,我的机器比较快,我把FOR循环改成500万到1000万次public class TestXiaolv {    /**
         * @param args
         */
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            long start = System.currentTimeMillis();        String[] s = new String[5000000];        for (int i = 0; i < s.length; i++) {
                
             s[i] = ""; 
                s[i] = null;  
                
            }
            
            long end = System.currentTimeMillis();
            System.out.println("程序执行时间:"+(end - start) + "ms");    }}可以试试看,一起讨论
      

  8.   

    2快吧只要new东西,就要在堆上运行搜索空间算法,并分配空间,所以1比较慢
      

  9.   

    是否会受到for循环的影响呢?JVM可能对其作了优化,貌似以前看过类似的帖子。
      

  10.   

    单独的一次测试,2好像比1快那么一点:public class test43
    {
    public static void main(String[] args)
    {
    long timestart,timeend;
    timestart=System.nanoTime();
    String str1="";
    timeend=System.nanoTime();
    System.out.println("str1时间:"+(timeend-timestart));
    timestart=System.nanoTime();
    String str2=null;
    timeend=System.nanoTime();
    System.out.println("str2时间:"+(timeend-timestart));
    }
    }
      

  11.   

    是呢,如果将21楼的代码建立空字符串和声明字符串空变量换一个位置,变化蛮大的。结果建立space串的时间为61737735,声明字符串变量的时间为:6427074,相差一个数量级呢,应该是For循环的影响。class BuildNullString {
    public static void buildNull(Integer con){
        int i=0;
    for (i = 0; i  < con.intValue(); i++) {
               String a=null;
        }
    System.out.println(i);}}class RunTime {/**
    * 通过方法名动态调用对象方法
    *
    * @param clsName
    *            调用类
    * @param methodName
    *            方法名
    * @param args
    *            方法参数
    * @return
    * @throws Exception
    */
    public static long invokeStaticMethod(String clsName, String methodName,
    Object[] params) throws Exception {
    long start = System.nanoTime();
    try {
    Class c = Class.forName(clsName);
    Class[] paramsClass = new Class[] {Integer.class};
    Method method = c.getMethod(methodName, paramsClass);
    method.invoke(c, params);
    } catch (Exception e) {
    e.printStackTrace();
    }
    long end = System.nanoTime();
    return end - start;
    }
    }public class TestSpaceForString {
    public static void main(String[] args) {
    Integer a=100000;
    Object[] param=new Object[]{a};
    try {long runTimeByColl=RunTime.invokeStaticMethod("BulidSpaceString", "bulidSpace", param);
    System.out.println("采用BulidSpaceString执行时间"+runTimeByColl);
    long runTime=RunTime.invokeStaticMethod("BuildNullString", "buildNull", param);
    System.out.println("采用BuildNullString转化方法执行时间"+runTime);
    System.out.println("微秒相差(runTimeByColl-runTime)=" +String.valueOf(runTimeByColl-runTime));
    } catch (Exception e) {
    e.printStackTrace();
    }
    }

      

  12.   


    一样的将 for 和输出全部去掉采用BuildNullString转化方法执行时间2528254
    采用BulidSpaceString执行时间1340673
    微秒相差(runTimeByColl-runTime)=-1187581还是 空串快一些!
      

  13.   

    但是实际应该是null快,到底那错了呢!!
      

  14.   

    第3个不知所云。
    前2个要从Opcode入手,2者的Opcode的区别在于
    1)String s1=""; 用的是  ldc [""在常量池的index]
    2)String s2=null; 用的是  aconst_null
    在运行时,第一个要访问2次内存,分别是读取ldc指令和读取index,而第2个只访问一次。
    所以,第二个快。