【问题标题】:Java storing an object vs directly calling its method? [duplicate]Java存储对象与直接调用其方法? [复制]
【发布时间】:2020-07-15 11:00:41
【问题描述】:

在 Java 中可以有两种方法调用方法:

在调用方法之前实例化和存储对象。

Foo foo = new Foo();
foo.method();

实例化并直接调用方法

new Foo().method();

对于您最终会再次使用foo 的情况,采用第一种方法是有意义的。

但是,假设我们知道至少对于当前要求,foo 仅用于调用method 一次,并且再也不会使用。哪个选项更适合?为什么?

我了解响应可能非常主观,因此我不是在寻找诸如更短的代码、可读性等原因(如果您愿意,请随时添加它们)。相反,我主要寻找基于性能、内存要求、垃圾收集等的参数,即使差异可以忽略不计。

之前有人问过这个问题,但是我找不到任何讨论上述论点的问题。

【问题讨论】:

  • 如果这是该方法的典型用法,那么可能Foo 应该是单例。或者method() 应该是静态的。
  • 本质上没有性能差异。选择可读性。
  • @ernest_k 我在这里考虑一个一般情况。我不在乎 Foo 是否是单例或方法是否是静态的。但是为了争论,我们假设它是非静态和非单例的。构造函数也可以参数化。我说的是一个特定情况,可以说它只使用一次。
  • @AndyTurner 我觉得由于对象永远不会存储在变量中,它会影响垃圾收集和内存空间。数量可能可以忽略不计,但仍然有微小的改善。只是一个假设,我在这里肯定是错的。
  • @kernel0707 字节码有所不同,因为在第一种情况下有一条附加指令存储在变量中。但是,重要的是要记住 JVM 不必逐字执行字节码:如果它看到不必要的变量分配,它可以跳过它。 JVM 非常聪明:不要试图猜测什么会更好。

标签: java performance object garbage-collection instance


【解决方案1】:

我主要寻找基于性能的论据,

没有区别。这个局部变量本质上是“免费的”。如果方法被频繁调用,JIT编译器会将局部变量优化掉,反正对象是刚刚创建的,所以它的引用在一级缓存中

内存要求,

如果优化器不删除它,局部变量可能会在线程调用堆栈上占用一些额外的字节空间。当方法返回时,这个空间会被回收和重用,如果不是更早的话。

垃圾回收,

GC通常不会收集对象,如果有一个局部变量从一个活线程中的堆栈帧指向它。对于长时间运行的方法,这可能很重要:使用局部变量意味着对象将存活更长时间。对于短期运行的方法,几乎​​没有区别。

使用局部变量,您可以在任一行上设置调试器断点。这允许您在对象创建之后和方法调用之前检查对象的状态。如果没有局部变量,您将不得不深入挖掘:

Foo foo = new Foo();
foo.method();

即使差异可以忽略不计。

如果您在解释模式下运行(而不是从编译到编译为本机),则本地变量写入和读取(astoreaload 字节码指令)的执行可能是可测量的。

【讨论】:

  • 我不认为单个变量的存储和加载是可测量的,即使在解释执行中也是如此。而且,正如您所说,JIT 可以消除这些变量或限制它们的范围,因此垃圾收集可能是可能的。回想一下,在未优化的执行中,Foo 实例在执行method() 时无法进行垃圾回收,因为该对象可通过方法中的this 引用获得。在优化的执行中,当不需要对象的内存时,两个引用都不会阻碍垃圾回收。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-05-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-18
  • 2017-04-13
  • 2014-06-28
相关资源
最近更新 更多