Java返回分配与分配然后返回。 (例如,在单例中)

发布于 2025-01-25 08:19:45 字数 692 浏览 3 评论 0原文

基本上,您可以拥有这样的代码:

baeldung.com

public static synchronized ClassSingleton getInstance() {
    if(instance == null) {
        instance = new ClassSingleton();
    }
    
    return instance;
}

您可以拥有像代码一样此:

我的版本:

public static synchronized ClassSingleton getInstance() {
    return instance = (instance == null) ? new ClassSingleton() : instance;
}

下面的代码以任何方式都更干净,但是Sonarlints Rule Java:S1121认为这是不合规的(主要的,代码味),

所以Sonarlint在谈论的可读性之外,还有更多吗?

我有一种奇怪的感觉,我的版本在返回之前一直在做任务,这是否可以表现不佳?

很高兴听到你们要说的话。

Basically, you can have code like this:

From: Baeldung.com

public static synchronized ClassSingleton getInstance() {
    if(instance == null) {
        instance = new ClassSingleton();
    }
    
    return instance;
}

and you can have code like this:

My Version:

public static synchronized ClassSingleton getInstance() {
    return instance = (instance == null) ? new ClassSingleton() : instance;
}

The code below is cleaner in any way, but SonarLints rule java:S1121 sees this as non-compliant (major, code smell)

So is there more behind this except the readability SonarLint is talking about?

I have a strange feeling that my version is doing always an assignment before returning, can this be a performance disbenefit?

Happy to hear what you guys have to say.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

沫离伤花 2025-02-01 08:19:45

是的,它可能具有[可能可以忽略的]性能影响。可以通过尝试编译并查看出来的内容来测试这一点。这是Javac 16.0.1的字节码:

Compiled from "ClassSingleton.java"
public class ClassSingleton {
  public ClassSingleton();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static synchronized ClassSingleton getInstance();
    Code:
       0: getstatic     #7                  // Field instance:LClassSingleton;
       3: ifnonnull     16
       6: new           #8                  // class ClassSingleton
       9: dup
      10: invokespecial #13                 // Method "<init>":()V
      13: putstatic     #7                  // Field instance:LClassSingleton;
      16: getstatic     #7                  // Field instance:LClassSingleton;
      19: areturn

  public static synchronized ClassSingleton getInstanceShort();
    Code:
       0: getstatic     #7                  // Field instance:LClassSingleton;
       3: ifnonnull     16
       6: new           #8                  // class ClassSingleton
       9: dup
      10: invokespecial #13                 // Method "<init>":()V
      13: goto          19
      16: getstatic     #7                  // Field instance:LClassSingleton;
      19: dup
      20: putstatic     #7                  // Field instance:LClassSingleton;
      23: areturn
}

通过long = bad的老年度量,第二版显然更糟。尽管如此,在所有情况下,它都只能执行2个额外说明。第一个dup重复堆栈上的最后一项,因此它可以将该额外项目使用到putstatic实例分配给堆栈上的最高值。我们可以推测,如果另一个线程在classSingleton上不同步,并且实例具有正确的属性,那么从理论上讲,我们可能会得到一些奇怪的行为,而实例可能无法正确设置。但是,考虑到同步为我们处理大多数,这似乎很不可能。

最后,JIT编译器可能会通过使用寄存器来消除对dup的需求,并且它有很大的机会弄清楚tat,它可以摆脱额外的putstatic也是如此。但是,我在JIT编译器上的经验不足,无法猜测它的行为。

话虽如此,只需使用第一个版本即可。它更容易读取并生成较短的字节码。

Yes it may have [probably negligible] performance implications. This can be tested by just trying to compile it and see what comes out. Here is the bytecode from Javac 16.0.1:

Compiled from "ClassSingleton.java"
public class ClassSingleton {
  public ClassSingleton();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static synchronized ClassSingleton getInstance();
    Code:
       0: getstatic     #7                  // Field instance:LClassSingleton;
       3: ifnonnull     16
       6: new           #8                  // class ClassSingleton
       9: dup
      10: invokespecial #13                 // Method "<init>":()V
      13: putstatic     #7                  // Field instance:LClassSingleton;
      16: getstatic     #7                  // Field instance:LClassSingleton;
      19: areturn

  public static synchronized ClassSingleton getInstanceShort();
    Code:
       0: getstatic     #7                  // Field instance:LClassSingleton;
       3: ifnonnull     16
       6: new           #8                  // class ClassSingleton
       9: dup
      10: invokespecial #13                 // Method "<init>":()V
      13: goto          19
      16: getstatic     #7                  // Field instance:LClassSingleton;
      19: dup
      20: putstatic     #7                  // Field instance:LClassSingleton;
      23: areturn
}

Via the age old metric of long=bad, the second version is clearly worse. In all seriousness though, it just performs 2 extra instructions in all cases. First dup duplicates the last item on the stack so it can then use that extra item to putstatic which assigns instance to the top value on the stack. We can speculate that if another thread is not synchronized on ClassSingleton, and instance has the correct attributes, then in theory we might get some weird behavior where instance might not be set correctly. However, that seems highly unlikely considering that synchronized handles most of that for us.

In the end though, the JIT compiler will probably remove the need for dup by using registers and it has a decent chance of figuring out tat it can get rid of that extra putstatic as well. However, I am not experienced enough with the JIT compiler to do more than speculate on how it might act.

That being said, just use the first version. It is way easier to read and generates shorter bytecode.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文