在Java中创建了多少个String对象?

时间:2016-02-15 08:57:22

标签: java string performance

我有以下Java代码:

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController
@synthesize leftView,rightView;

- (void)viewDidLoad {
    [super viewDidLoad];
}

- (IBAction)FirstAction:(id)sender {

    FirstView * test1 = [[FirstView alloc]initWithFrame:CGRectMake(0, 0, rightView.frame.size.width, rightView.frame.size.height)];
    test1.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
    [rightView addSubview:test1];
}

- (IBAction)SecondAction:(id)sender {

    SecondView * test2 = [[SecondView alloc]initWithFrame:CGRectMake(0, 0, rightView.frame.size.width, rightView.frame.size.height)];
    test2.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
    [rightView addSubview:test2];
}

- (IBAction)ThirdAction:(id)sender {

    ThirdView * test3 = [[ThirdView alloc]initWithFrame:CGRectMake(0, 0, rightView.frame.size.width, rightView.frame.size.height)];
    test3.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
    [rightView addSubview:test3];
}

@end

对于某人创建了5个对象。(“Java”,“虚拟”,“机器”,“Java虚拟”,“Java虚拟机”)。

但我知道这段代码等于:

String a = "Java" + "Virtual" + "Machine";

这里没有一个对象?

创建了多少个String对象?

编辑:

以下代码的相同问题:

String a = new StringBuilder("Java").append("Virtual").append("Machine").toString();

创建了多少个String对象?

2 个答案:

答案 0 :(得分:2)

创建了确切的1个字符串对象,编译器将String a = "Java" + "Virtual" + "Machine";优化为String a = "JavaVirtualMachine";

javap -c Test的输出可以看出这一点,我使用System.out.println来阻止编译器完全优化它:

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

  public static void main(java.lang.String...);
    Code:
       0: ldc           #2                  // String JavaVirtualMachine
       2: astore_1
       3: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
       6: aload_1
       7: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      10: return
}

答案 1 :(得分:1)

编译器会优化代码,使其等于:

String a = "JavaVirtualMachine";

更有趣的问题可能是它的作用:

int x = 5;
String a = "foo" + x + "bar";

在这种情况下,编译器将创建StringBuilder并附加所有值。 这大致可以转换为这段代码:

int x = 5;
String a = new StringBuilder().append("foo").append(x).append("bar").toString();

但是如果你在一个循环中连接String,编译器将在每次迭代中创建一个StringBuilder。所以如果你有这样的代码:

String[] errorMessages = getErrorMessages();
String output = "Found the following error messages:";
for(int i = 0; i < errorMessages.length(); i++){
    output += "\n" + (i+1) + ": " + errorMessages[i];
}

这会(再次粗略地)转化为:

String[] errorMessages = getErrorMessages();
String output = "Found the following error messages:";
for(int i = 0; i < errorMessages.length(); 
    output = new StringBuilder(output).append('\n')
            .append((i+1)).append(": ").append(errorMessages[i]).toString();
}

如上所述,这会在每次迭代中创建一个新的StringBuilder。因此,在这些情况下,最好不要依赖编译器来实现它的魔力,创建自己的StringBuilder,并在整个迭代过程中使用相同的对象:

String[] errorMessages = getErrorMessages();
StringBuilder builder = new StringBuilder("Found the following error messages:");
for(int i = 0; i < errorMessages.length(); i++){
    builder.append('\n').append((i+1)).append(": ").append(errorMessages[i]);
}