【问题标题】:Java Incremental operator query (++i and i++) [duplicate]Java增量运算符查询(++i和i++)[重复]
【发布时间】:2014-08-16 19:42:08
【问题描述】:

我有以下代码:

public class Book {
    private static int sample1(int i) {
        return i++;
    }
    private static int sample2(int j) {
        return ++j;
    }

    public static void main(String[] arguments){ 
        int i = 0;
        int j = 0;
        System.out.println(sample1(i++)); //0
        System.out.println(sample1(++i)); //1
        System.out.println(sample2(j++));//1
        System.out.println(sample2(++j));//2
        System.out.println(i);//2
        System.out.println(j);//2
    }
}

我的预期输出是 cmets。实际输出如下:

0
2
1
3
2
2

我对函数调用和 incemental 运算符感到困惑。有人可以解释一下实际结果吗?

【问题讨论】:

  • 你一遍又一遍地增加同一个变量。每次要增加时都需要将其重置为零。
  • 你知道Java是按值传递的,所以sample1实际上只是return i;,而sample2是return j + 1,对吧?嗬!错字已修复。谢谢@ElliottFrisch
  • @DavidEhrmann 你的意思是pass-by-value
  • 一个是前置的,一个是后置​​的。这有帮助吗?
  • @ChrisTarazi 我知道我一遍又一遍地增加同一个变量。我只是想解释一下这些值是如何逐步增加的。

标签: java increment


【解决方案1】:

首先你要知道x++++X的区别;

如果是x++

首先将使用当前值,然后将其递增。 这意味着您将获得 x 的现值进行操作,如果您 下次使用 x 会得到递增的值;

如果是++x

首先当前值将被递增,接下来将使用(递增的值),这意味着您将获得递增的值 在本次手术中,在本次手术后其他。

现在让我们拆分代码并单独讨论它们

方法:sample1():

private static int sample1(int i) {
    return i++;
}

此方法将采用 int 并首先返回它,然后尝试递增,但在返回变量 i 后将超出范围,因此它永远不会 完全增加了。 exp in: 10-> out 10

方法:sample2():

private static int sample2(int j) {
    return ++j;
}

此方法将接受一个 int 并先递增它,然后返回它。 exp in: 10-> out 11

在这两种情况下,只有变量会在本地发生变化,这意味着如果你从主方法调用,主方法的变量将不受变化的影响 (因为 sample1() 和 sample2() 正在复制变量)

现在是main方法的代码

System.out.println(sample1(i++)); // it's giving sample1() `i=0` then making `i=1` 
                                  //  so  sample1() will return 0 too;

System.out.println(sample1(++i)); // it's making `i=2` and then giving sample1() `i=2`
                                  // so sample1() will return 2;

System.out.println(sample2(j++)); // it's giving sample2() `j=0` then making `j=1` 
                                  // so sample2() will return 1;

System.out.println(sample2(++j)); // it's making `j=2` giving sample2() `j=2` then  
                                  // so sample2() will return 3;

【讨论】:

    【解决方案2】:

    形成你的榜样,

      private static int sample1(int i) {
        return i++;
      }
      private static int sample2(int j) {
      return ++j;
      }
    
      public static void main(String[] arguments)
      { 
      int i = 0;
      int j = 0;
      System.out.println(sample1(i++)); //0
      System.out.println(sample1(++i)); //1
      System.out.println(sample2(j++));//1
      System.out.println(sample2(++j));//2
      System.out.println(j);//2
      System.out.println(j);//2
      }
    
    1. i = 0; sample1(i++) -> 它通过 '0'-> 在 sample1 中返回 i++ 所以,0(++) 这里它返回 0 但递增到 1 ,所以 println = 0 但最后 i 取 1
    2. i = 1; sample1(++i) -> 它通过 '2'-> 在 sample1 返回 i++ 所以,2(++) 这里它返回 2,所以 println = 2
    3. j = 0; sample2(j++) -> 它通过 '0'-> 在 sample2 中返回 ++j 所以,(++)0 这里它返回 1,所以 println = 1。
    4. j = 1; sample2(++j) -> 它通过 ++1 => 2,在 sample2 中返回 ++j 所以,(++)2 这里它返回 3,所以 println = 3。但是增量以 sample2 结束,而不是在 main 所以 j 仍然是 2。
    5. j = 2
    6. j = 2

    【讨论】:

      【解决方案3】:

      由于sample1sample2 只是修改了它们自己的局部变量ij(不是调用方法的那些),所以如果我们在不进行这些修改的情况下重写它们会更清楚:

      private static int sample1(int i) {
          return i;   // was 'i++', which evaluates to the old i
      }
      private static int sample2(int j) {
          return j + 1;   // was '++j', which evaluates to j after incrementing
      }
      

      此时,只需将它们替换为原位就很简单了——sample1(...) 变为 ...sample2(...) 变为 ... + 1

      int i = 0;
      int j = 0;
      System.out.println(i++);
      System.out.println(++i);
      System.out.println((j++) + 1);
      System.out.println((++j) + 1);
      System.out.println(i);
      System.out.println(j);
      

      我们可以通过将增量分成它们自己的命令来使这一点更清晰。 i++ 的计算结果是 i 的原始值,所以就像在运行周围的命令之后增加 i 一样;相比之下,++i 就像在运行周围命令之前增加i 。所以我们得到:

      int i = 0;
      int j = 0;
      System.out.println(i);
      i++;
      ++i;
      System.out.println(i);
      System.out.println(j + 1);
      j++;
      ++j;
      System.out.println(j + 1);
      System.out.println(i);
      System.out.println(j);
      

      。 . .此时应该可以直接跟踪并查看它将输出什么。

      这一切都有意义吗?

      【讨论】:

      • 这是否意味着在方法sample1 return ireturn i++ 是同一件事?
      • 是的,因为 Java 通过值而不是引用传递方法参数。 sample1 中的本地 i 在递增之前超出范围
      • OP 刚刚更改:System.out.println(j); System.out.println(j);到 System.out.println(i); System.out.println(j);你也请更新你的答案吗?他两次打印相同的变量(不会影响您的答案,但无论如何......)
      • @NenadBulatovic:完成!感谢您的提醒。
      【解决方案4】:

      它们都将变量 i 加一,例如 i = i + 1;

      区别在于

      ++i 先增加值再返回

      i++ 先返回值再递增

      这种行为差异在 for 循环中无关紧要。

      如果你想知道区别,试试这个:

      int x = 0;
      int y = x++;
      
      int x = 0;
      int y = ++x;
      

      这里x++ 返回值然后递增,但++x 先递增值然后返回该值

      【讨论】:

        【解决方案5】:

        第一次打印

        调用前:i = 0

        调用后递增

        sample1 被调用,值为 0

        样本1返回0,丢弃增量

        调用后:i = 1

        第二次打印

        调用前:i = 1

        调用前递增

        sample1 被调用,值为 2

        sample1返回2,丢弃增量

        调用后:i = 2

        第三次打印

        调用前:j = 0

        调用后递增

        sample2 被调用,值为 0

        sample2 递增 0 到 1,返回它

        打印1个

        将 j 增加到 1

        调用后:j = 1

        第四次打印

        调用前:j = 1

        调用前递增

        将 j 增加到 2

        sample2 被调用,值为 2

        sample2 2 到 3 的增量,返回它

        3 被打印出来

        调用后:j = 2

        第五次打印

        打印我

        2 被打印出来

        第 6 次打印

        打印 j

        2 被打印出来

        【讨论】:

          【解决方案6】:

          简单:
          1) 第一次通话:
          a) 将 i (==0) 提供给 sample1(),它返回 0(然后增加参数 i,并被丢弃)。
          b) 因为 i++ 而增加 i。 我现在 1 岁
          c) 打印函数结果:0。

          2) 第二次调用:
          a) 由于 ++i 而增加 i。 我现在 2 岁
          b) 将 i (==2) 提供给 sample1(),它返回 2(然后增加参数 i,并被丢弃)
          c) 打印函数结果:2.

          3) 第三次调用:
          a) 将 j (==0) 提供给 sample2(),这会增加参数,因此返回 1。
          b) 由于 j++ 而增加 j。 j 现在是 1
          c) 打印函数结果: 1.

          4) 第四次调用:
          a) 由于 ++j 而增加 j。 j 现在是 2
          b) 将 j (==2) 提供给 sample2(),这会增加参数,因此返回 3。
          c) 打印函数结果: 3.

          5 & 6) 第五次和第六次通话:
          a) 打印 j 的值:2。

          这里要记住的关键是 i++ 在将变量作为参数传递后递增,而 ++i 在将变量作为参数传递之前递增。

          希望对你有帮助

          【讨论】:

          • 为什么会被丢弃?
          • 嗨@misguided,它被丢弃,因为方法参数的范围仅对方法是本地的:这意味着当方法返回其结果时,你得到的是变量的副本,并且在例如 sample1() ,增量 i++ 操作发生在您掌握方法结果之后。 Java 总是按值传递方法参数,而不是按引用传递(例如与您可以选择的 C++ 或 VB 相反)...
          • ... 因此,您永远不能为函数提供原始类型变量,在该函数中对其进行修改,并希望在该函数之外看到修改:您将看到修改的唯一方法首先通过本地参数向方法提供副本,然后将修改后的参数的副本返回给代码的调用部分。
          • 这基本上是@Jason 在他对 ruakh 回答的评论中解释的内容
          【解决方案7】:

          您正在体验前缀和后缀运算符的乐趣。

          前缀运算符++i将变量i加一在表达式中使用它之前,其中后缀运算符(i++)在递增之前在表达式中使用i它。

          这意味着你的方法sample1 没有做任何事情;它对包含i 的表达式求值,但由于该表达式是返回语句,局部变量i 超出范围,我们无法再对其进行修改。

          相比之下,sample2 在返回之前会增加 j 的本地副本,这就是为什么您打印的 j 的值比您预期的要高。

          【讨论】:

            猜你喜欢
            • 2023-01-14
            • 2017-08-11
            • 2011-01-23
            • 1970-01-01
            相关资源
            最近更新 更多