这就是“长”的工作时间吗(在Java中)?

这就是“长”的工作时间吗(在Java中)?,java,Java,请看以下Java代码: class PerformanceTest2{ public static void main(String args[]){ Long sum = 0L; for(int i=0;i<Integer.MAX_VALUE;i++) sum += i; System.out.println("Sum = " + sum); } } 因此,每次都会创建一个新对象。java

请看以下Java代码:

class PerformanceTest2{

    public static void main(String args[]){

        Long sum = 0L;

        for(int i=0;i<Integer.MAX_VALUE;i++)
            sum += i;

        System.out.println("Sum = " + sum);
    }
} 
因此,每次都会创建一个新对象。java不支持C++返回返回引用的特性,因此我们可以编写:

sum.longValue() += i;
LongWrapper sum = new LongWrapper(0L);
for (int i = 0;i < Integer.MAX_VALUE; i++)
{
    sum.setValue(sum.getValue() + i);
}
System.out.println("Sum = " + sum);

可能不必在循环中每次都创建sum对象?我说得对吗

它不调用构造函数。它使用:

for (int i = 0; i < Integer.MAX_VALUE; i++)
{
   long tmp = sum.longValue(); // Unboxing
   tmp += i;
   sum = Long.valueOf(tmp); // Boxing
}
包装器对象是故意不可变的——它们很容易被设计成可变的,但不可变性通常是一个非常有用的特性。如果您想编写自己的可变包装器类型,非常欢迎使用-此时您可以编写如下代码:

LongWrapper sum = new LongWrapper(0L);
for (int i = 0; i < Integer.MAX_VALUE; i++)
{
    sum.add(i);
}
System.out.println("Sum = " + sum);
或者可能:

sum.longValue() += i;
LongWrapper sum = new LongWrapper(0L);
for (int i = 0;i < Integer.MAX_VALUE; i++)
{
    sum.setValue(sum.getValue() + i);
}
System.out.println("Sum = " + sum);

它不调用构造函数。它使用:

for (int i = 0; i < Integer.MAX_VALUE; i++)
{
   long tmp = sum.longValue(); // Unboxing
   tmp += i;
   sum = Long.valueOf(tmp); // Boxing
}
包装器对象是故意不可变的——它们很容易被设计成可变的,但不可变性通常是一个非常有用的特性。如果您想编写自己的可变包装器类型,非常欢迎使用-此时您可以编写如下代码:

LongWrapper sum = new LongWrapper(0L);
for (int i = 0; i < Integer.MAX_VALUE; i++)
{
    sum.add(i);
}
System.out.println("Sum = " + sum);
或者可能:

sum.longValue() += i;
LongWrapper sum = new LongWrapper(0L);
for (int i = 0;i < Integer.MAX_VALUE; i++)
{
    sum.setValue(sum.getValue() + i);
}
System.out.println("Sum = " + sum);

java没有C++类引用。此外,原语类型的内置包装器类被故意设置为不可变的。做出此决定的原因之一是,运行时可能会缓存特定值的包装器实例,并避免创建新对象,这需要调用valueOf,而不是通过new分配新对象;编译器为装箱而执行此操作。

< P> java没有C++类引用。此外,原语类型的内置包装器类被故意设置为不可变的。做出此决定的原因之一是,运行时可能会缓存特定值的包装器实例,并避免创建新对象,这需要调用valueOf,而不是通过new分配新对象;编译器这样做是为了装箱

因此,每次都会创建一个新对象。java支持C++类吗 返回引用的特性,以便我们可以编写 可能:

如果使用Long,则显式地从Java请求包装器类型。包装器类型的约定是:它们是不可变的。而C++中的不变性要求不可修改的内部必须给予外部。但是C++类似的引用会精确地做到这一点。我们跳过const引用部分,因为这对C++也没有帮助。

可能不必在循环中每次都创建sum对象?我说得对吗

理论上是的,但是如果你想要这种行为,为什么不从一开始就用一个不长的右键呢

因此,每次都会创建一个新对象。java支持C++类吗 返回引用的特性,以便我们可以编写 可能:

如果使用Long,则显式地从Java请求包装器类型。包装器类型的约定是:它们是不可变的。而C++中的不变性要求不可修改的内部必须给予外部。但是C++类似的引用会精确地做到这一点。我们跳过const引用部分,因为这对C++也没有帮助。

可能不必在循环中每次都创建sum对象?我说得对吗


理论上是的,但是如果你想要这种行为,为什么不从一开始就用一个不长的右键呢

我邀请您看看我在这里设置的测试用例:

您的代码速度慢不是因为混合了long和int类型,而是因为您使用的是long而不是long。Long类型是一个合适的对象,不可启动,因此每次为变量指定一个新值时,都会构造一个新对象,如果新值的缓存对象已经存在,则可能是一个例外。相对而言,这是一项昂贵的手术


正如您将从示例代码中看到的,将循环更改为添加long而不是int不会使其运行得更快。加速的方法是将第一个变量改为long而不是long。

我邀请您看看我在这里设置的测试用例:

您的代码速度慢不是因为混合了long和int类型,而是因为您使用的是long而不是long。Long类型是一个合适的对象,不可启动,因此每次为变量指定一个新值时,都会构造一个新对象,如果新值的缓存对象已经存在,则可能是一个例外。相对而言,这是一项昂贵的手术


正如您将从示例代码中看到的,将循环更改为添加long而不是int不会使其运行得更快。加速的方法是将第一个变量改为long而不是long。

其他人已经解释了为什么long比long花费的时间更长,以及如何使用long。valueOf`可能会稍微快一点

请不要让这成为不长时间使用的理由。您的整个系统吞吐量时间很可能不会受到影响

如果存在影响性能的紧密循环,则使用原语long
那里有一个Jon描述的或来自apache commons的手卷包装器。

其他人已经解释了为什么Long比Long花费的时间更长,以及如何使用Long.valueOf`可能会稍微快一点

请不要让这成为不长时间使用的理由。您的整个系统吞吐量时间很可能不会受到影响



如果存在影响性能的紧密循环,则使用原语long there,这是Jon描述的或apache commons提供的手动包装。

sum为“long”的程序运行时间为1.660s,而sum为“long”的程序运行时间为9.367s。这就是原因吗?Java不是每次都在循环中创建sum吗?@AmitL:是的,装箱几乎肯定是原因。每次迭代都会调用Long.valueOf方法,但这并不一定会创建新的值。例如,保证缓存-128和127(包括-128和127)之间的值。示例代码将很快超出{-128,127}的范围。我认为可以肯定地说,几乎每次迭代都会通过Long.valueOf调用构造函数。至少在最初通过循环时。而且可能在后续过程中也会出现这种情况,因为Java不太可能缓存任何接近Long的Integer.MAX_值实例。事实上,我有点惊讶于JIT没有相应地简化代码。可能是因为这完全是错误的做法。您通常使用原语,必要时让编译器自动将其装箱到对象。@Voo:不要忘记JIT编译器在进行JIT编译时必须注意的任何优化都需要时间。花在优化合理代码上的时间比计算如何使愚蠢的代码看起来不愚蠢更有意义。总和为“长”的程序运行时间为1.660秒,而这一总和为“长”的程序运行时间为9.367秒。这就是原因吗?Java不是每次都在循环中创建sum吗?@AmitL:是的,装箱几乎肯定是原因。每次迭代都会调用Long.valueOf方法,但这并不一定会创建新的值。例如,保证缓存-128和127(包括-128和127)之间的值。示例代码将很快超出{-128,127}的范围。我认为可以肯定地说,几乎每次迭代都会通过Long.valueOf调用构造函数。至少在最初通过循环时。而且可能在后续过程中也会出现这种情况,因为Java不太可能缓存任何接近Long的Integer.MAX_值实例。事实上,我有点惊讶于JIT没有相应地简化代码。可能是因为这完全是错误的做法。您通常使用原语,必要时让编译器自动将其装箱到对象。@Voo:不要忘记JIT编译器在进行JIT编译时必须注意的任何优化都需要时间。花在优化合理代码上的时间比计算如何使愚蠢的代码看起来不愚蠢更有意义。那么,在给定的程序中,是否每次循环都会创建sum?希望不是,当然。你问了很久,你会明白的。就这么简单。如果你不想这样,就用long`来代替。那么在给定的程序中,每次循环都会创建sum吗?希望不是,当然。你问了很久,你会明白的。就这么简单。如果你不想这样,就用long`来代替。事实上,在那种情况下,我看不出有任何理由使用long。多亏了自动装箱,我们可以在必要时获得对象,并且不会有性能开销。如果我理解正确,您的意思是您可以使用例如一个集合并在其中放置一个long,自动装箱将负责转换。正确,只需知道自动装箱也会在javap中使用valueOf check进行转换,并且会有相同的开销。但编译器仅在必要时自动装箱原语。因此,在可能的情况下,我们获得了原语的优点,而没有任何缺点。如果我们换一种方式来做,我们就会遇到我们在这里看到的性能问题。在使用Long进行Autoboxxing之前,它有助于避免额外的函数调用,但今天呢?我看不出有什么好处。事实上,在那种情况下,我看不出有什么理由使用long。多亏了自动装箱,我们可以在必要时获得对象,并且不会有性能开销。如果我理解正确,您的意思是您可以使用例如一个集合并在其中放置一个long,自动装箱将负责转换。正确,只需知道自动装箱也会在javap中使用valueOf check进行转换,并且会有相同的开销。但编译器仅在必要时自动装箱原语。因此,在可能的情况下,我们获得了原语的优点,而没有任何缺点。如果我们换一种方式来做,我们就会遇到我们在这里看到的性能问题。在Autoboxing使用Long之前,它有助于避免额外的函数调用, 但是今天呢?看不出有什么好处。