Java 如果只使用两次,创建新对象引用是否会更快?

Java 如果只使用两次,创建新对象引用是否会更快?,java,object,optimization,reference,casting,Java,Object,Optimization,Reference,Casting,我有一个关于教学优化的问题。如果一个对象要在两个语句中使用,那么创建一个新的对象引用是更快,还是应该在两个语句中直接调用该对象 就我的问题而言,对象是对象的向量的一部分(此示例来自没有ArrayList的精简版Java)。以下是一个例子: AutoEvent ptr = ((AutoEvent)e_autoSequence.elementAt(currentEventIndex)); if(ptr.exitConditionMet()) {currentEventIndex++; return;

我有一个关于教学优化的问题。如果一个对象要在两个语句中使用,那么创建一个新的对象引用是更快,还是应该在两个语句中直接调用该对象

就我的问题而言,对象是对象的
向量
的一部分(此示例来自没有ArrayList的精简版Java)。以下是一个例子:

AutoEvent ptr = ((AutoEvent)e_autoSequence.elementAt(currentEventIndex));
if(ptr.exitConditionMet()) {currentEventIndex++; return;}
ptr.registerSingleEvent();
AutoEvent
是所讨论的类,而
e_autoSequence
是AutoEvent对象的
向量。
AutoEvent
包含两个有问题的方法:
exitConditionMet()
registerSingleEvent()

因此,该代码也可以写成:

if(((AutoEvent)e_autoSequence.elementAt(currentEventIndex)).exitConditionMet()) 
    {currentEventIndex++; return;}
((AutoEvent)e_autoSequence.elementAt(currentEventIndex)).registerSingleEvent();
这比上面的速度快吗

我知道浇铸过程很慢,所以这个问题实际上有两个方面:另外,如果我没有浇铸对象,哪一个会得到更高的优化


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

第一种解决方案会更快

原因是赋值比方法调用更快。 在第二种情况下,您将调用两次方法elementAt(),这将使其速度变慢,JVM可能无法优化此代码,因为它不知道elementAt()中到底发生了什么


还要记住Vector的方法是同步的,这使得每个方法调用由于锁获取而变得更慢。

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

第一种解决方案更全面:

  • 只调用一次vector
    elementAt
    方法。这实际上是这里最昂贵的操作,所以只做一次是一个不错的性能胜利。同时做两次可能会让你面临一些比赛条件
  • 仅执行一次强制转换操作。在moderns JVM上,强制转换非常便宜,但成本仍然很低
  • 它的可读性更强。你得到一个物体,然后用它做两件事。如果你得到了两次,那么读者必须在心里明白你得到的是同一个物体。最好只获取一次,并将其分配给具有良好名称的变量
  • 局部变量的单个赋值(如第一个解决方案中的
    ptr
    )非常便宜,而且通常是免费的
    ——Java JIT编译器足够聪明,可以在这里生成高度优化的代码

另外,Vector已经过时了。考虑转换为<代码> ARARYLISTAB/COD>。通过使用通用ArrayList,您不需要显式强制转换,而且它比
向量快得多(因为它不同步,因此锁定开销较小)

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


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

(向量
或数组列表
上的
elementAt
方法是
O(1)
且便宜。如果列表是一个链表,其中
elementAt
实现了
O(N)
,那么该调用可能很昂贵,并且进行1次或2次调用之间的差异可能很大……)

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



我不能说
ArrayList
是否更合适。在这种情况下,您可能需要
Vector

提供的线程安全性。此处代价高昂的操作可能是将对象从
Vector
中取出,而不是将结果分配给变量。因此,第一个解决方案应该更快。这似乎是一个非常需要优化的小问题。即使仅仅考虑演员的表现,我也觉得有点不对。您似乎表示您运行的是“简化”版本的Java,因此您可能正在移动环境或类似环境中工作,但我仍然怀疑这种优化是否真的必要。“你想达到什么目的?”杰克·金说实话,这更像是一种好奇心。我确实理解它几乎没有实际的区别,特别是考虑到向量的微小大小。不过还是有点奇怪。@JakeKing-在很多情况下,这种优化可能非常重要。我已经将CPU绑定代码的总体速度提高了一倍多,只进行了一些这样的优化。这并不总是重要的(如果有疑问,你应该先分析一下!),但当它真的重要时,它绝对值得去做。坦率地说,我听到的最好的建议是“编写Java,编写惯用Java,让编译器来了解细节”。编译器寻找人们所做的常见模式,并尽可能优化它,因此玩游戏和询问编译器通常会适得其反。+1表示“可读”参数。这边