如果它只使用两次,创建一个新的对象引用会更快吗?

时间:2013-02-12 04:02:50

标签: java object optimization reference casting

我对指令优化有疑问。如果要在两个语句中使用一个对象,创建一个新的对象引用会更快,还是应该直接在两个语句中调用该对象?

出于我的问题的目的,该对象是Vector个对象的一部分(此示例来自没有ArrayLists的Java的简化版本)。这是一个例子:

AutoEvent ptr = ((AutoEvent)e_autoSequence.elementAt(currentEventIndex));
if(ptr.exitConditionMet()) {currentEventIndex++; return;}
ptr.registerSingleEvent();

AutoEvent是有问题的类,e_autoSequence是AutoEvent对象的VectorAutoEvent包含两个有问题的方法:exitConditionMet()registerSingleEvent()

因此,此代码可以替换为:

if(((AutoEvent)e_autoSequence.elementAt(currentEventIndex)).exitConditionMet()) 
    {currentEventIndex++; return;}
((AutoEvent)e_autoSequence.elementAt(currentEventIndex)).registerSingleEvent();

这比上面的更快吗?

我理解投射过程很慢,所以这个问题实际上是双重的:另外,如果我没有投射对象,那么会更加高度优化?

请记住,这仅用于对象的两种用途。

4 个答案:

答案 0 :(得分:2)

第一种解决方案全面改善:

  • 只有一次调用到vector elementAt方法。这实际上是这里最昂贵的操作,所以只做一次就是一场不错的表现。同样做两次可能会让你达到一些竞争条件。
  • 只能进行一次操作。在现代JVM上,演员阵容非常便宜,但仍然有一点点成本。
  • 更具可读性恕我直言。你得到一个对象,然后用它做两件事。如果你得到它两次,那么读者必须在心理上弄清楚你得到的是同一个物体。最好把它拿一次,然后把它分配给一个名字好的变量。
  • 本地变量的单一分配(如第一个解决方案中的ptr非常便宜并且通常是免费的 - Java JIT编译器足够智能在这里生成高度优化的代码。

P.S。 Vector已经过时了。考虑转换为ArrayList<AutoEvent>。通过使用通用ArrayList,您不需要显式转换,它比Vector快得多(因为它不同步,因此锁定开销较小)

答案 1 :(得分:0)

第一种解决方案会更快。

原因是赋值比方法调用工作得更快。 在第二种情况下,你将调用方法elementAt()两次,这会使它变慢,JVM可能无法优化这段代码,因为它不知道elementAt()究竟发生了什么。

还要记住,Vector的方法是同步的,这使得每次方法调用都会因锁定获取而变慢。

答案 2 :(得分:0)

我不知道这里的“创建一个新的对象引用”是什么意思。以下代码((AutoEvent)e_autoSequence.elementAt(currentEventIndex))可能会被转换为获取序列元素的字节码,将其强制转换为AutoEven并将结果引用存储在堆栈中。局部变量ptr作为其他局部变量也存储在堆栈中,因此分配对is的引用只是将4个字节从一个堆栈槽复制到另一个堆栈槽。这是非常非常快的操作。现代JVM不进行引用计数,因此分配引用可能与分配int值一样便宜。

答案 3 :(得分:0)

让我们先得到一些术语。您的代码不会“创建新的对象引用”。它从Vector获取现有对象引用(一次或两次)。


要回答你的问题,获取一次并将引用放入临时变量(可能)要快一点。但差别很小,不太可能显着,除非你在循环中多次这样做。

elementAtVector上的ArrayList方法O(1)且价格便宜。如果列表是一个链接列表,其实现O(N)对于elementAt,然后该调用可能很昂贵,并且进行1或2次调用之间的差异可能很大......)

一般来说,您应该考虑算法的复杂性,但除此之外,您不应该花时间优化...直到您有可靠的分析证据来告诉您优化的位置。


我不能说ArrayList是否更合适。这可能是您需要 Vector提供的线程安全的情况。