【问题标题】:Why javac sometimes creates unnecessary copies of variables?为什么 javac 有时会创建不必要的变量副本?
【发布时间】:2015-04-10 00:10:08
【问题描述】:

我的代码如下所示:

boolean[] array = new boolean[200];
int[] indexes = {10, 42, 62, 74};
while(true) {
    //some code here
    StringBuilder sb = new StringBuilder();
    for (int j : indexes) {
        sb.append(array[j] ? '1' : '0');
    }
}

为此的字节码:

ASTORE 3 //"indexes" array
...
ALOAD 3
ASTORE 8
ALOAD 8
ARRAYLENGTH
...

我不确定为什么 javac 将 ref 复制到另一个本地变量中。

【问题讨论】:

  • 这个字节码的哪一部分 "copy ref to array into another local var" ?
  • @Jean-FrançoisSavard ALOAD 3 后跟 ASTORE 8

标签: java javac bytecode


【解决方案1】:

for-each 循环被转换成这样:

{
    int[] hidden_array_ref = indexes;
    int hidden_length = hidden_array_ref.length;
    for(int hidden_counter = 0; hidden_counter < hidden_length; hidden_counter++) {
        int j = hidden_array_ref[hidden_counter];
        sb.append(array[j] ? '1' : '0');
    }
}

特别注意int[] hidden_array_ref = indexes;。这就是你要问的副本。

编译器是这样做的,所以如果你写这样的东西:

for(int j : indexes) {
    indexes = new int[0];
    sb.append(array[j] ? '1' : '0');
}

分配给indexes 不会影响循环。

【讨论】:

  • 不确定如何回答“为什么 javac 将 ref 复制到另一个本地变量中”
  • @Jean-FrançoisSavard 它是 indexes 的引用被复制(到另一个隐藏的局部变量,我称之为 hidden_array_ref
  • 哦,我错过了。
  • 哇,泰。我被认为在循环内更改数组是程序员的问题,或者根本不允许。我现在尝试使用正常的 for 循环,如下所示:int[] array = new int[10]; for (int i = 0; i &lt; array.length; i++) {} 并且没有生成副本。所以我们允许在这个循环中对数组进行一些不可预知的操作?
  • @saroff:定义很简单,如果你使用for(var : expression)expression 只会被计算一次。它可能是另一个局部变量,就像你的情况一样,但想想for(byte b: Files.readAllBytes(pathToMyFile));在这种情况下,文件在循环开始时只读取一次,而不是在每次迭代中......
猜你喜欢
  • 2014-10-29
  • 1970-01-01
  • 2014-06-30
  • 2021-10-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多