关于增量:Java增量运算符查询(++ i和i ++)

Java Incremental operator query (++i and i++)

本问题已经有最佳答案,请猛点这里访问。

我有以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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
    }
}

我期望的输出在注释中。实际产量如下:

1
2
3
4
5
6
0
2
1
3
2
2

我对函数调用和乱伦操作符感到困惑。有人能解释一下实际结果吗?


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

1
2
3
4
5
6
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

1
2
3
4
5
6
7
8
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。所以我们得到:

1
2
3
4
5
6
7
8
9
10
11
12
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);

. …在这一点上,应该可以直接跟踪并查看它将输出什么。

这一切都有道理吗?


首先,你需要知道x++++x之间的区别;

如果是x++

首先使用当前值,然后递增。也就是说,如果你下次使用x将得到递增值;

如果是++x

首先,当前值将递增,然后将使用它(递增值),这意味着您将获得递增值。在此操作和此操作之后的其他操作。

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

方法:sample1():

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

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

方法:sample2():

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

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

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

现在主要的方法代码

1
2
3
4
5
6
7
8
9
10
11
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;


你正在体验前缀和后缀操作符的乐趣。

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

这意味着方法sample1不做任何事情;它评估包含i的表达式,但由于该表达式是一个返回语句,所以局部变量i超出了范围,我们无法再修改它。

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


以你为例,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  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
  }
  • i=0;sample1(i++)->它在sample1中通过"0"->返回i++,所以,0(++)这里它返回0,但递增到1,所以println=0,但最后我取1
  • i=1;sample1(++i)->它在sample1中通过'2'->返回i++so,2(++)这里返回2,所以println=2
  • j=0;sample2(j++)->它在sample2返回中通过了'0'->j所以,(++)0这里它返回1,所以println=1。
  • j=1;sample2(++j)->它通过++1=>2,在sample2中返回++j so,(++)2这里它返回3,所以println=3。但增量以sample2结束,而不是以所以J仍然保持2。
  • J=2
  • J=2

  • 两种方法都将变量i增加一个,如i = i + 1;

    区别在于:

    ++我先递增值,然后返回它

    i++首先返回值,然后递增

    这种行为差异在for循环中并不重要。

    如果你想知道不同之处,试试这个:

    1
    2
    3
    4
    5
    int x = 0;
    int y = x++;

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

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


    第一打印

    呼叫前:i=0

    调用后递增

    使用值0调用sample1

    示例1返回0,增量被丢弃

    通话后:i=1

    第二打印

    呼叫前:i=1

    呼叫前递增

    使用值2调用sample1

    sample1返回2,增量被丢弃

    通话后:i=2

    第三打印

    呼叫前:j=0

    调用后递增

    使用值0调用sample2

    sample2递增0到1,返回它

    1印制

    将j增加到1

    通话后:j=1

    第四打印

    呼叫前:j=1

    呼叫前递增

    将J增加到2

    使用值2调用sample2

    sample2递增2到3,返回它

    3印制

    通话后:J=2

    第五打印

    版画I

    2印制

    第六打印

    版画J

    2印制


    容易的:1)第一次呼叫:a)向sample1()提供i(=0),sample1()返回0(然后递增参数i,该参数将被丢弃)。b)因i++而递增i。我现在1岁了。c)打印函数结果:0。

    2)第二呼叫:a)增量i是因为+i.i现在是2。b)向sample1()提供i(=2),sample1()返回2(然后递增参数i,该参数将被丢弃)c)打印功能结果:2。

    3)第三呼叫:a)向sample2()提供j(=0),它使参数递增,因此返回1。b)因为j++而增加j。J现在是1岁。c)打印功能结果:1。

    4)第四呼叫:a)增量j是因为+j。j现在是2。b)向sample2()提供j(=2),它使参数递增,因此返回3。c)打印功能结果:3。

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

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

    希望这有帮助