为什么此代码会产生这些答案?

时间:2017-11-28 15:51:34

标签: java math methods

我目前正在学习Java,我正在努力理解Java中数学背后的逻辑。在本课程的旧测试中,存在如下问题。然后我应该写出这段代码将要显示的内容。我的问题是,我不理解两个代码中的两个数字。

在第一个测试类中,整数Tal打印为15.好的,我可以按照那里的逻辑。

它是这样的:

c.setNbrOf(4+1) = 5
int tal = c.getNbrOf()+10 = 15

BUT

当我将相同的逻辑应用于第二个测试类时,我得到了错误的答案。 我的逻辑是:

c.setNbrOf(4+1) = 5
c2.setNbrOf(5) +1 = 6

由于客户c = c2,这意味着c的值也为6(?)

因此,int tal = 6 + 5即11。

但事实并非如此。当我运行它时,它是12。

为什么方法++tal中的andra会影响其全局值?我以为这只是当地的。

我希望我不清楚。

运行测试类需要客户类。

public class Customer {

    private String name;
    private int nbrOf;

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name=name;
    }

    public int getNbrOf() {
        return this.nbrOf;
    }

    public void setNbrOf (int nbrOf) {
        this.nbrOf=nbrOf;
    }

}

第一个测试类。

public class Test {

     public static void main(String[] args) {

         Customer c = new Customer();
         c.setName("Kund1");
         c.setNbrOf(4+1);

         int tal = c.getNbrOf()+10;

         System.out.println("Namn: "+c.getName()+" ålder: "+c.getNbrOf());
         foo(c, tal+3);
         System.out.println("Namn: "+c.getName()+" ålder: "+c.getNbrOf());
         System.out.println("Tal: "+tal);
    }

    public static void foo(Customer p, int x) {
        p.setName("Kund2");
        p.setNbrOf(x);
        x ++;
    }
}

第二个。

public class Test {
     public static void main(String[] args) {
         Customer c = new Customer();
         c.setName("K1");

         Customer c2 = c;
         c.setNbrOf(4+1);
         c2.setNbrOf(c.getNbrOf()+1);
         int tal = c.getNbrOf()+5;
         System.out.println("Namn: "+c.getName()+" ålder: "+c2.getNbrOf());
         andra(c, ++tal);
         System.out.println("Namn: "+c.getName()+" ålder: "+c.getNbrOf()+", 
         "Tal: "+tal);
    }
    public static void andra(Customer p, int tal) {
         p.setName("K2");
         tal=9;
         p.setNbrOf(tal);
    }
}

6 个答案:

答案 0 :(得分:1)

当您编写++tal时,表示tal = tal + 1;,然后返回tal的新值。因此,当您将++tal传递给函数时,您已经运行了两个命令。

另外,您应该知道tal函数内andra的设置值是本地的,并且不会更改函数外部tal的值。因此,调用talandra(c, ++tal)的最终值为12

答案 1 :(得分:0)

c = c2 - 此行表示从现在起您希望c指向包含c2的内存中的相同空间。从现在开始,cc2中的所有更改都会影响另一个更改(两个不同的引用指向同一个对象)

答案 2 :(得分:0)

andra(c, ++tal);

是:

tal = tal + 1; //12
andra(c, tal);

答案 3 :(得分:0)

andra(c, ++tal);与:

相同
tal = tal + 1;
andra(c, tal);

虽然andra(c, tal++);类似于:

andra(c, tal);
tal = tal + 1;

预增量和后增量运算符在计算表达式之前(之前)或之后(之后)递增值。这不是“本地”与“全球”范围。它会影响范围内变量的范围。

此外,在您的andra方法中,您明确设置tal = 9,因此它会忽略传递的参数。

答案 4 :(得分:0)

因为我们实际上只有一个对象,所以我们可以在这里忽略OO并用简单的数学写它: 如果c2 = c,那么只有一个对象,因此只有一个NbrOf

     c.setNbrOf(4+1);

NbrOf = 4 + 1 = 5

     c2.setNbrOf(c.getNbrOf()+1);

NbrOf = NbrOf + 1 = 5 + 1 = 6

     int tal = c.getNbrOf()+5;

int tal = NbrOf + 5 = 6 + 5 = 11;

     andra(c, ++tal);

这会将tal增加1并将该值分配给tal,它相当于

      tal = tal + 1;
      andra(c, tal);   

然而,andra(c, tal);内的tal是复制值(所有基元都是通过副本传递的,而不是通过引用传递的。所以指定tal = 9不会影响外部的tal!重命名它在andra(c, tal);内,以便更容易理解。

结论,tal = 12

答案 5 :(得分:0)

[编辑]修正了传递值和clone()

的错误部分

你问两个问题,所以让我们分别附上每个问题。

A)代码中特定点的cc2的价值是多少。

要回答这个问题,你需要意识到只是说“c = c2”并不能说出完整的故事。首先创建Customer对象的两个实例,并分别在cc2中存储对它们的引用。当您指定c = c2时,您将两个变量存储到Customer的同一(单个)实例的引用;另一个会收集垃圾。现在,可以通过方法调用将剩余对象的状态更改为c OR c2,因为它们都引用同一个实例。

这意味着

c.setNbrOf(4+1);               // AAA
c2.setNbrOf(c.getNbrOf()+1);   // BBB

将两个相同的nbrOf成员变量的值更改为两次,它们看起来就像是分开的,因为您已将c设为别名c2(反之亦然,具体取决于您希望如何看待它)。行AAA c.nbrOf确实等于5;要计算BBB行中发生的事情,你需要将线条分成几部分。使用一个参数调用c2.setNbrOf(),该参数实际上是两个事物之和的表达式,即调用c.getNbrOf()和数字文字“1”的结果。对c.getNbrOf()的调用返回5并且表达式在将结果6传递给c2.setNbrOf()的调用之前将其加1。由于cc2是彼此的别名,因此当您使用getNbrOfc致电c2时,您会得到“6”的结果两者都指向同一个实例。

B)为什么方法中的++ tal会影响它的全局值?

嗯,它不会影响全局值,它只是看起来那样,因为你再次遇到一个用作方法参数的表达式。

andra(c, ++tal);      // CCC

andra()的调用没有将'++ tal'传递给方法,它首先计算表达式,实际上在本地范围内将tal递增1,然后计算tal的值确定要发送给方法调用的值。这意味着,是的,tal在CCC行之前是11,但在参数评估期间,变量的值在调用之前被更改为12。那么为什么当你能清楚地看到

时,代码会打印'12'
public static void andra(Customer p, int tal) {
         p.setName("K2");
         tal=9;            // DDD
         p.setNbrOf(tal);
    }

行DDD应该导致p.nbrOf的值为9?嗯,是的,p.nbrOf的值确实在DDD之后的行中变为'9',就像p.name变为“K2”一样。这导致您的问题为什么代码打印'12'而不是'9'。这是因为你必须考虑另一件事,那就是范围。方法andra()实际上创建了一个名为'tal'的新存储位置,该位置与main()中具有相同名称的变量的位置不同,即andra()隐藏名称'tal '这样当它将'tal'的值改为9时,它只会改变局部变量而不是调用代码中具有相同名称的变量。

我不得不说这个示例代码正在做一些事情来惹你上去,这也意味着它正在努力帮助你理解语言处理符号表的不同方式,这可能令人困惑。通过在测试代码中使用tal作为局部变量并且作为方法中的参数名称,示例代码没有任何改进,这是一种不好的做法,但是在这里用来使练习更加困难。

尝试使用此代码查看实际情况。

// actually Test3 would be a better name, but I'll leave that to you
public class Test {   
     public static void main(String[] args) {
         Customer c = new Customer();
         c.setName("K1");

         Customer c2 = c;
         c.setNbrOf(4+1);
         c2.setNbrOf(c.getNbrOf()+1);
         int tal = c.getNbrOf()+5;
         int tal2 = ++tal;
         System.out.println("Namn: "+c.getName()+" ålder: "+c2.getNbrOf()+" reference to c:"+ c);
         andra(c, tal2);
         System.out.println("Namn: "+c.getName()+" ålder: "+c.getNbrOf()+", 
         Tal: "+tal);
    }
    public static void andra(Customer p, int tal3) {
         p.setName("K2");
         tal3=9;
         System.out.println("BEFORE - reference to p: "+p+" tal: "+tal3+" p.nbrOf:"+p.getNbrOf());
         p.setNbrOf(tal3);
         System.out.println("AFTER - reference to p: "+p+" tal: "+tal3+" p.nbrOf:"+p.getNbrOf());

    }
}

这应该显示几件事,p的引用应该是与c中的引用不同的值,使用唯一的变量和参数名称可以更清楚地了解正在评估的变量或已更改,并将++tal表达式移到方法调用之外应显示如何在andra()内更改变量。