链接方法与在Java中生成临时变量是否会影响内存分配?

链接方法与在Java中生成临时变量是否会影响内存分配?,java,garbage-collection,heap-memory,allocation,Java,Garbage Collection,Heap Memory,Allocation,在Java中,如果我在一个对象上执行多个方法,我可以链接它们,或者我可以创建一个临时变量,就像这样 锁链 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); 显然,在本例中,差异可以忽略不计,但当您在数千个字符串/其他对象上执

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

锁链

    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);
显然,在本例中,差异可以忽略不计,但当您在数千个字符串/其他对象上执行此操作时,可能会产生影响

我的问题是,在不进行额外的对象分配或填充堆(从而使GC更快地被调用)方面,其中一个更“有效”吗

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

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
}
从“TestNoTmp.java”编译而来
公共类TestNoTmp{
公共TestNoTmp();
代码:
0:aload_0
1:invokespecial#1//方法java/lang/Object。“:()V
4:返回
公共静态void main(java.lang.String[]);
代码:
0:iconst_4
1:anewarray#2//class java/lang/String
4:dup
5:iconst_0
6:ldc#3//将这些
8:aastore
9:dup
10:iconst_1
11:ldc#4//字符串是__
13:aastore
14:dup
15:iconst_2
16:ldc#5//串一些_
18:aastore
19:dup
20:iconst_3
21:ldc#6//字符串
23:aastore
24:astore_1
25:aload_1
26:astore_2
27:aload_2
28:排列长度
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//fieldjava/lang/System.out:Ljava/io/PrintStream;
48:aload 5
50:iconst_0
51:iconst_4
52:invokevirtual#8//方法java/lang/String。子字符串:(II)Ljava/lang/String;
55:iconst_0
56:iconst_2
57:invokevirtual#8//方法java/lang/String。子字符串:(II)Ljava/lang/String;
60:invokevirtual#9//方法java/io/PrintStream.println:(Ljava/lang/String;)V
63:iinc 4,1
66:转到33
69:返回
}
公共类TestTmp{
公共测试tmp();
代码:
0:aload_0
1:invokespecial#1//方法java/lang/Object。“:()V
4:返回
公共静态void main(java.lang.String[]);
代码:
0:iconst_4
1:anewarray#2//class java/lang/String
4:dup
5:iconst_0
6:ldc#3//将这些
8:aastore
9:dup
10:iconst_1
11:ldc#4//字符串是__
13:aastore
14:dup
15:iconst_2
16:ldc#5//串一些_
18:aastore
19:dup
20:iconst_3
21:ldc#6//字符串
23:aastore
24:astore_1
25:aload_1
26:astore_2
27:aload_2
28:排列长度
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//方法java/lang/String。子字符串:(II)Ljava/lang/String;
52:astore 6
54:aload 6
56:iconst_0
57:iconst_2
58:invokevirtual#7//方法java/lang/String。子字符串:(II)Ljava/lang/String;
61:astore 6
63:getstatic#8//fieldjava/lang/System.out:Ljava/io/PrintStream;
66:aload 6
68:invokevirtual#9//方法java/io/PrintStream.println:(Ljava/lang/String;)V
71:iinc 4,1
74:转到33
77:返回
}

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

str.substring(0,4).substring(0,2)
第一次调用substring必须生成一个新的String对象,因为str无法修改。类似地,在新字符串对象上对substring的第二次调用将创建另一个新字符串对象

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


为了回答您的问题,这对对象分配和GC影响没有影响。

这就是您的答案。虽然
javac
没有做太多优化,但这些小事情对生成的字节码没有影响。此外,您可能希望专注于真正的性能瓶颈。即使temp变量确实影响字节码,这也不会是一个。虽然字节码略有不同,所以我不确定这是否会产生影响,或者我的假设是否正确(我可以用一种不会产生影响的方式编写我的示例),这不会产生影响。