Java:如果我在类中使用封装的原始数据类型,它会慢多少?

时间:2013-01-14 20:17:08

标签: java c++ porting

我正在翻译C ++代码,并且有很多使用typedef。我不能 在Java中这样做,所以我做的是:

// C++
typedef unsigned int BucketKey; 


// Java
public class BucketKey {
    public int val;
}

我不是Java专家,实际上是新手,我想知道它有多贵 是否使用BucketKey,而不是直接使用int?

请注意,我需要为至少5种类型执行此操作。

感谢

6 个答案:

答案 0 :(得分:2)

它增加了巨大的开销,特别是如果你有数组。我建议编写一个测试程序进行比较。

在Java中int[100]创建一个包含100个int的数组 - 类似于C / C ++,Integer[100]YourObjectContainingAnIntMember[100]有一个包含100个引用(指针)到100个不同对象的数组。

更不用说BucketKey对象将具有引用语义,但int具有类似于C ++的值语义:

BucketKey x = new BucketKey(100);
BucketKey y = x
y.value = 200; // x will change as well

int x = 100;
int y = x;
y = 200; // x will remain 100

同样值得补充的是,C ++中的typedef也不会创建新类型。所以BucketKey变量的类型只是整数 - 但Java没有typedef来调用int更多的方法。具有不同类型的C ++解决方案将是

struct BucketKey {
    value x;
}

答案 1 :(得分:1)

请注意,您的问题与装箱无关:java int是原始类型,其盒装版本为java.lang.Integer。您正在质疑对类成员的访问是否比访问原始变量慢。大多数Java性能问题基本上没有答案:存在差异,但这种差异取决于许多因素,包括:

  • 硬件架构
  • Java版
  • 操作系统

但是,除非您正在进行高频交易,否则如果您正确地构建了关于封装的程序,那么与生产率的巨大提升相比,性能影响将是完全可接受的下行。


如果你真的遇到这样的性能问题并考虑使用JVM,那么你应该选择比Java更现代的编程语言。

事实是JVM不支持Value类。但是,Scala有:

http://docs.scala-lang.org/overviews/core/value-classes.html

答案 2 :(得分:1)

如果可能的话,使用原始int。拳击/拆箱的惩罚并不高,但你应该确定这一点。在任何情况下,它看起来都不像你的例子中的装箱/拆箱。你正在做一个原始对象决定。

无论如何,除非你正在制作一个实时系统或类似的东西,否则你不应该太担心这个。

我同意Peter Lawrey的观点。使用visual vm识别瓶颈。我也写了一篇简短的教程 [source]

答案 3 :(得分:1)

它的不同取决于你使用它的程度。如果你每秒使用它一百万次。它没有太大的区别。如果你每秒使用它1000万次你会注意到它,如果你每秒使用它1亿次,原始的速度会快很多倍。

您应该编写一个简单明了的工作程序,然后才能对其进行分析(例如使用VisualVM)以找到瓶颈。很可能你的瓶颈会出现在你无法预测的地方。

答案 4 :(得分:0)

有一些顶部拳击和拆箱值。话虽如此,与“典型”程序中的其余处理相比,开销通常可以忽略不计。

我建议使用最坏情况(就密钥访问次数而言)构建一个测试用例,如果你看到有一个灵活密钥类型的价值,就可以两种方式测量性能。

如果您不需要灵活地更改密钥类型作为实际问题,请使用 int

答案 5 :(得分:0)

使用拳击课有合理的要求。

例如,如果参数为null,则在参数中使用框而不是基元允许JAX-B避免在XML元素中包含属性。那是为了防止

<employee name='Henry' id=null years=null />

但应该是

<employee name='Henry' />

因此,如果出现这样的要求,也可以使用盒装实例。

我没有Java编译器的专业知识,但我希望编译器能够处理优化。我的心理实验似乎说这是一个预期的,相对简单的优化。

我的想法是,如果Java编译器无论如何都会优化装箱,那么在某些时候你需要采取实例化盒装实例的命中。为什么不早点去享受它的所有功能和设施呢?