1

在我看来,在这两种方法中,第一种方法存在与string concat和相关的性能问题toCharArray。但有人告诉我,这两个操作都是在编译时发生的,所以没有性能开销。

如果这是真的,那么为什么编译时操作不是性能开销?

private final static char[] DigitTens = {
     ("0000000000"+ "1111111111"+"2222222222"+"3333333333"+"4444444444" //
     +"5555555555"+"6666666666"+"7777777777"+"8888888888"+"9999999999")
      .toCharArray();             
};

对比:

private final static char[] DigitTens = {
    '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
    '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
    '2', '2', '2', '2', '2', '2', '2', '2', '2', '2',
    '3', '3', '3', '3', '3', '3', '3', '3', '3', '3',
    '4', '4', '4', '4', '4', '4', '4', '4', '4', '4',
    '5', '5', '5', '5', '5', '5', '5', '5', '5', '5',
    '6', '6', '6', '6', '6', '6', '6', '6', '6', '6',
    '7', '7', '7', '7', '7', '7', '7', '7', '7', '7',
    '8', '8', '8', '8', '8', '8', '8', '8', '8', '8',
    '9', '9', '9', '9', '9', '9', '9', '9', '9', '9',
};
4

3 回答 3

3

带有 s 的字符串连接表达式+是一个常量表达式,并在编译时解析(JLS §15.28)。但是,toCharArray()调用是在运行时执行的。总体而言,您的第一个片段等效于:

private final static char[] DigitTens;

static {
    DigitTens = "0000000000111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999"
            .toCharArray();
}

你的第二个片段相当于:

private final static char[] DigitTens;

static {
    DigitTens = new char[100];
    DigitTens[0] = '0';
    DigitTens[1] = '0';
    ...
    DigitTens[99] = '9';
}

(您可以通过 字节码自己查看javap -c

最终,不要担心这里的性能;你可能不会看到有什么不同。选择您认为更清晰、更易于管理的任何内容。编译代码所花费的时间通常是无关紧要的,因为编译阶段实际上应该只发生一次,之后您将处理.class包含字节码的生成文件。

我还要指出,在这种特定情况下,DigitTens[i]is simple i / 10,假设i在 0-99 范围内,包括在内。

于 2013-10-04T16:08:09.533 回答
1

回答这个问题

如果这是真的,那么为什么编译时操作不是性能开销?

他们是。但是它们在每个程序创建时只发生一次,并且在程序运行期间永远不会发生。

我认为我不必担心编译器性能(除了查看构建的整体结构)。我会为了清晰而编写代码,除非它成为一个问题,否则我不会担心性能。这同样适用于运行时性能。

于 2013-10-04T16:05:26.473 回答
0

“编译时”性能开销会影响开发人员,并可能在他/她的整个生命周期中花费一毫秒。

运行时性能开销每秒可能发生 x 次,成本要高得多。

至于您的具体示例,第二种方法稍微更有效(可以说是以清晰为代价),因为它消除了在运行时调用 toCharArray 的需要。

于 2013-10-04T16:08:13.657 回答