Java 缓存在自动装箱中的作用

Java 缓存在自动装箱中的作用,java,autoboxing,Java,Autoboxing,有效Java中的第5项Joshua Bloch说,除非对象非常重,否则不要创建对象池,但在jdk源代码中,我在Integer类中看到了IntergerCache,在Long和Character类中看到了LongCache和CharacterCache public class autobox { /** * @param args */ public static void main(String[] args) {

有效Java中的第5项Joshua Bloch说,除非对象非常重,否则不要创建对象池,但在jdk源代码中,我在Integer类中看到了IntergerCache,在Long和Character类中看到了LongCache和CharacterCache

    public class autobox {

        /**
         * @param args
         */
        public static void main(String[] args) {
            long start=System.nanoTime();
            Integer sum=0;
            sum=sum+94;  //1-- takes most time
            long end=System.nanoTime();
            System.out.println(end-start);
            for(int i=0;i<1000;i++)
                sum=sum+i;
            end=System.nanoTime();
            System.out.println(end-start);  //--2
            sum=0;
            for(int j=5;j<1000;j++)
                sum=sum+j;
            end=System.nanoTime();
            System.out.println(end-start);  //--3
        }
    }
看起来语句1创建的对象太多了,都是为了只创建一个整数对象!。我不明白这背后的原因。尽管文档中提到-XX:AutoBoxCacheMax=但我得到一个无法识别的错误VM选项“AutoBoxCacheMax=0”。
缓存不应该只保留已创建的对象,而不是创建不必要的对象吗?

您无法控制正在测量的对象。请看这一页

1在您的代码中,您有:

1      long start=System.nanoTime();
2      Integer sum=0;
3      sum=sum+94;  //1-- takes most time
4      long end=System.nanoTime();
假设第3行需要很多时间。实际上是第二行,见下文

2你的系统。输出。打印。。。包含在2中。三,。时间尺度。这是一个问题,因为打印到控制台非常昂贵,应该从您的测量中删除

为了说明这一点,我重新整理了您的代码并获得了完全不同的度量:

    long start;
    long end;

    start=System.nanoTime();
    System.out.println("println test");
    end = System.nanoTime();
    System.out.println("Time 1: " + (end - start));

    start=System.nanoTime();
    Integer sum=0;
    end = System.nanoTime();
    System.out.println("Time 2: " + (end - start));

    start=System.nanoTime();
    sum=sum+94;
    end = System.nanoTime();
    System.out.println("Time 3: " + (end - start));

    start=System.nanoTime();
    for(int i=0;i<1000;i++) {
        sum=sum+i;
    }
    end = System.nanoTime();
    System.out.println("Time 4: " + (end - start));

    sum=0;
    start=System.nanoTime();
    for(int j=5;j<1000;j++) {
        sum=sum+j;
    }
    end=System.nanoTime();

    System.out.println("Time 5: " + (end - start));

再说一遍,请不要对这些数字读太多。这是一个没有popper预热阶段的测试,没有考虑JIT编译等的影响。

为什么要使用包装器类型?整数和=0;这是一种性能很好的方法,这就是为什么Java有基元类型。这只是一个示例程序。不是一个要求。但可能有一个。比如说,如果我必须将其作为值放入HashMap中,我觉得很像。加载Integer类时,每个程序只创建一次缓存。检查缓存是否已经包含对象可能比完全创建整个缓存更昂贵。因为它是一个包装器而不是一个原语,所以它需要做额外的工作来完成相同的任务。现在,对于HashMap的需求,您不能给出原语。因此,您无法在那里进行优化。
    long start;
    long end;

    start=System.nanoTime();
    System.out.println("println test");
    end = System.nanoTime();
    System.out.println("Time 1: " + (end - start));

    start=System.nanoTime();
    Integer sum=0;
    end = System.nanoTime();
    System.out.println("Time 2: " + (end - start));

    start=System.nanoTime();
    sum=sum+94;
    end = System.nanoTime();
    System.out.println("Time 3: " + (end - start));

    start=System.nanoTime();
    for(int i=0;i<1000;i++) {
        sum=sum+i;
    }
    end = System.nanoTime();
    System.out.println("Time 4: " + (end - start));

    sum=0;
    start=System.nanoTime();
    for(int j=5;j<1000;j++) {
        sum=sum+j;
    }
    end=System.nanoTime();

    System.out.println("Time 5: " + (end - start));
println test
Time 1: 140572
Time 2: 360759
Time 3: 3420
Time 4: 139639
Time 5: 130619