链接方法与在 Java 中创建临时变量会影响内存分配吗? [英] Does chaining methods vs making temporary variables in Java impact memory allocation?

查看:22
本文介绍了链接方法与在 Java 中创建临时变量会影响内存分配吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 Java 中,如果我在一个对象上执行多个方法,我可以链接它们,或者我可以创建一个临时变量,就像这样

In Java, if I'm performing multiple methods on an object, I can chain them, or I can make a temporary variable, like so

链接

    System.out.println( str.substring(0,4).substring(0,2));

临时变量

    String tmp = str.substring(0,4);
    tmp = tmp.substring(0,2);
    System.out.println(tmp);

显然,在此示例中差异可以忽略不计,但是当您对数千个字符串/某个其他对象执行此操作时可能会产生影响.

Obviously, the difference is negligible in this example, but could make an impact when you're doing this over thousands of strings/some other object.

我的问题是,在不进行额外的对象分配或填充堆(从而使 GC 更快被调用)方面,这些方法之一是否更有效"?

My question is, is one of these more "efficient" in terms of not making extra object allocations or filling the heap (and thus making GC get called sooner)?

我试图在几个字符串的循环中比较两者的字节码,但它看起来很相似,最后几行没有.我不了解所有的字节码调用,所以我不确定这些调用是否与分配新对象有关.

I tried to compare the bytecodes of the two in a loop over a couple strings, but it looks similar, sans for the last few lines. I don't understand all the bytecode calls, so I'm not sure if any of these have to do with allocating new objects.

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

  public static void main(java.lang.String[]);
    Code:
       0: iconst_4
       1: anewarray     #2                  // class java/lang/String
       4: dup
       5: iconst_0
       6: ldc           #3                  // String These
       8: aastore
       9: dup
      10: iconst_1
      11: ldc           #4                  // String Are__
      13: aastore
      14: dup
      15: iconst_2
      16: ldc           #5                  // String Some_
      18: aastore
      19: dup
      20: iconst_3
      21: ldc           #6                  // String Strings
      23: aastore
      24: astore_1
      25: aload_1
      26: astore_2
      27: aload_2
      28: arraylength
      29: istore_3
      30: iconst_0
      31: istore        4
      33: iload         4
      35: iload_3
      36: if_icmpge     69
      39: aload_2
      40: iload         4
      42: aaload
      43: astore        5
      45: getstatic     #7                  // Field java/lang/System.out:Ljava/io/PrintStream;
      48: aload         5
      50: iconst_0
      51: iconst_4
      52: invokevirtual #8                  // Method java/lang/String.substring:(II)Ljava/lang/String;
      55: iconst_0
      56: iconst_2
      57: invokevirtual #8                  // Method java/lang/String.substring:(II)Ljava/lang/String;
      60: invokevirtual #9                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      63: iinc          4, 1
      66: goto          33
      69: return
}

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

  public static void main(java.lang.String[]);
    Code:
       0: iconst_4
       1: anewarray     #2                  // class java/lang/String
       4: dup
       5: iconst_0
       6: ldc           #3                  // String These
       8: aastore
       9: dup
      10: iconst_1
      11: ldc           #4                  // String Are__
      13: aastore
      14: dup
      15: iconst_2
      16: ldc           #5                  // String Some_
      18: aastore
      19: dup
      20: iconst_3
      21: ldc           #6                  // String Strings
      23: aastore
      24: astore_1
      25: aload_1
      26: astore_2
      27: aload_2
      28: arraylength
      29: istore_3
      30: iconst_0
      31: istore        4
      33: iload         4
      35: iload_3
      36: if_icmpge     77
      39: aload_2
      40: iload         4
      42: aaload
      43: astore        5
      45: aload         5
      47: iconst_0
      48: iconst_4
      49: invokevirtual #7                  // Method java/lang/String.substring:(II)Ljava/lang/String;
      52: astore        6
      54: aload         6
      56: iconst_0
      57: iconst_2
      58: invokevirtual #7                  // Method java/lang/String.substring:(II)Ljava/lang/String;
      61: astore        6
      63: getstatic     #8                  // Field java/lang/System.out:Ljava/io/PrintStream;
      66: aload         6
      68: invokevirtual #9                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      71: iinc          4, 1
      74: goto          33
      77: return
}

推荐答案

在您的示例中,您使用的是不可变的字符串.在您的代码中:

In your example, you're working with Strings, which are immutable. In your code:

str.substring(0,4).substring(0,2)

第一次调用 substring 必须生成一个新的 String 对象,因为 str 不能被修改.类似地,在该新 String 对象上第二次调用 substring 将创建另一个新 String 对象.

the first call to substring must generate a new String object because str cannot be modified. Similarly, the second call to substring on that new String object will create another new String object.

字节码的差异仅仅是编译器调用方法顺序的结果.在 TestTmp 的情况下,所有字符串操作都发生在调用 PrintStream 之前.对于 TestNoTmp,String 调用发生在 PrintStream 调用中,这在您查看代码时非常合乎逻辑.

The difference in bytecodes is simply a result of the order in which the compiler calls methods. In the TestTmp case, all the string manipulation occurs before the call to PrintStream. For TestNoTmp, the String calls happen within the PrintStream call, which is very logical when you look at the code.

为了回答您的问题,这在对象分配和 GC 影响方面没有区别.

To answer your question, this will make no difference in terms of object allocation and therefore GC impact.

这篇关于链接方法与在 Java 中创建临时变量会影响内存分配吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆