Java双倍与双倍:类型与原始类型
我很好奇Java类和原始类型之间的性能差异。所以我创建了一个基准,发现类的类型比原始类型慢3倍-7倍。 (在本地机器上OSX,7倍3倍的ideone)Java双倍与双倍:类型与原始类型
下面是测试:
class Main {
public static void main(String args[]) {
long bigDTime, littleDTime;
{
long start = System.nanoTime();
Double d = 0.0;
for (Double i = 0.0; i < 1432143.341; i += 0.1) {
d += i;
}
long end = System.nanoTime();
bigDTime = end - start;
System.out.println(bigDTime);
}
{
long start = System.nanoTime();
double d = 0.0;
for (double i = 0.0; i < 1432143.341; i += 0.1) {
d += i;
}
long end = System.nanoTime();
littleDTime = end - start;
System.out.println(littleDTime);
}
System.out.println("D/d = " + (bigDTime/littleDTime));
}
}
那么,为什么是Double类型这么多慢?为什么它甚至被实现以允许数学运算符?
那么为什么Double类型慢得多?
因为价值被包裹其中需要分配,回收,内存管理以及getter和setter对象内
为什么即使实现,让数学运算符?
因为autobox是为了让您使用这样的包装而不用担心它们不是普通的值。你想不能有ArrayList<Double>
?性能为并非总是需要,根据情况可能可以接受3至7倍性能下降。优化是一个并不总是存在的要求。
在任何情况下都是如此,使用随机访问元素的LinkedList
可能会矫枉过正,但这并不意味着根本不应该实现LinkedList
。这也不意味着对少量随机访问使用链表会严重干扰性能。
最后一点说明:在基准测试之前,应让虚拟机热身。
Double
是盒装的double
。因此,一般来说编译代码必须先检查Double
为null,然后再做任何事情。这当然比无所事事慢。
Double
(和其他原始版本的盒装版本)很有用,因为它是Object
。这使您可以将它传递给需要Object
的函数,并将其转换回Double
其他地方。更有用的是,它允许泛型类型包含它:泛型类型不能包含double
或任何其他基元,但它可以包含Double
。
你通常不会使用Double
,Integer
等(偶尔Integer
等等都可以存储在“可选”值很有用 - 你可能希望它是null
有时这是因为Double
是NaN
可能性较小)
原因Double
存在如下。 Java有两种主要类型的值:对象(本质上类似于没有算术的C/C++指针)和原始值(例如double
)。类似ArrayList
可以定义为接受任何Object
,它允许用户将String
,File
或其他任何他们喜欢的东西存储在一个中 - 但像double
这样的原始值不包含在此定义中。因此存在像Double
这样的类可以使像ArrayList
这样的类更容易地存储double
,而不需要ArrayList
的作者为所有基元类型创建特殊版本。
由于需要装箱和取消装箱,速度很慢。这是预期的行为。 – 2013-03-23 03:16:46
@HovercraftFullOfEels这是有道理的,但它仍然看起来像很多开销。 – 2013-03-23 03:19:31
这是一个很大的开销。因此,您应该避免在时间关键的代码中使用原始包装类型。 – 2013-03-23 03:20:16