首页 > 试题广场 >

given the following code,what

[单选题]
下面代码运行结果是?
class Value{
    public int i=15;
}
public class Test{
    public static void main(String argv[]){
        Test t=new Test( );
        t.first( );
    }

public void first( ){
    int i=5;
    Value v=new Value( );
    v.i=25;
    second(v,i);
    System.out.println(v.i);
}

public void second(Value v,int i){
    i = 0;
    v.i = 20;
    Value val = new Value( );
    v = val;
    System.out.println(v.i+" "+i);
   }
}

  • 15 0 20
  • 15 0 15
  • 20 0 20
  • 0 15 20
推荐
这题选A,考察的是值传递与引用传递,Java中原始数据类型都是值传递,传递的是值得副本,形参的改变不会影响实际参数的值, 引用传递传递的是引用类型数据,包括String,数组,列表, map,类对象等类型,形参与实参指向的是同一内存地址,因此形参改变会影响实参的值。
编辑于 2015-02-04 11:46:59 回复(19)
发表于 2016-08-17 23:09:10 回复(91)
可能有人会选择B,包括我刚开始也是。总以为v不是已经指向了val了吗??为什么还是20呢?不应该是15吗?
其实,原因很简单。现在我们把second()换一下
publicvoidsecond(Value tmp,inti){
    i = 0;
    tmp.i = 20;
    Value val = newValue( );
    tmp = val;
    System.out.println(tmp.i+" "+i);
   }
这个tmp其实相当于是一个指向原来first中的V这个对象的指针,也就是对v对象的引用而已。但是引用是会改变所指的地址的值的。
所以在second中当tmp.i= 20的时候,就把原来first中的v的i值改为20了。接下来,又把tmp指向了新建的一个对象,所以在second中的tmp
现在指的是新的对象val,i值为15.
当执行完毕second后,在first中在此输出v.i的时候,应为前面second中已经把该位置的i的值改为了20,所以输出的是20.
至于疑惑v指向了val,其实只是名字的问题,在second中的v实践也是另外的一个变量,名字相同了而已,这个估计也是纠结的重点。
简单的总结,不对希望可以提出来,谢谢!
发表于 2015-09-17 15:59:21 回复(31)
本题考查两个知识点:
1. 局部变量名字会屏蔽点外作用域同名字变量
2. 函数的参数传递问题

下面直接在代码上进行详细分析:

classValue{
    publicinti=15;
}
publicclassTest{
    publicstaticvoidmain(String argv[]){
        Test t=newTest( );
        t.first( );
    }
 
publicvoidfirst( ){
    inti=5;//注意这个i是局部变量
    Value v=newValue( );
    v.i=25;//创建了一个Value对象,并把此对象的属性i赋值25(默认值为15)
    second(v,i);//v (v中的属性i值为25) 和 局部变量i 传进函数second
    System.out.println(v.i);//v的属性i在second函数中被改为了20
}
 
publicvoidsecond(Value v,inti){
    i = 0;//second函数中的局部变量,和之前的i没关系
    v.i = 20;//将传进的V的属性i改为20
    Value val = newValue( );
    v = val;//新创建的Value对象val,属性i值为15,并将v指向val对象,v已经和之前传进来的对象没关系了
    System.out.println(v.i+" "+i);//此时v的属性i为15,先输出 15(v.i) 0(i)
   }
}
所以,输出 15 0 20
发表于 2016-03-08 18:27:20 回复(20)
Java中的对象参数是按照引用变量的值来传递的。具体见下面解析:
classValue{
    publicinti=15;
}
publicclassTest{
    publicstaticvoidmain(String argv[]){
        Test t=newTest( );
        t.first( );
    }
 
publicvoidfirst( ){
    inti=5;
    Value v=newValue( );
    v.i=25;
    second(v,i);
    System.out.println(v.i);//first方法中的v的指向未改变过
}
 
publicvoidsecond(Value v,inti){//这里将引用变量v拷贝了一份,即多了一个引用变量v,v指向与first方法中的v一样的对象
    i = 0;
    v.i = 20;//改变拷贝的v指向的对象的i值,由于此时v指向与first方法中的v一样的对象,所以first方法中的对象i值变为20
    Value val = newValue( );//创建一个新对象
    v = val;//改变拷贝的v指向的对象,此时拷贝的v与val指向同一个对象,而first方法中的v的指向是不变的
    System.out.println(v.i+" "+i);
   }
所以Java中参数都是按值传递的。
发表于 2016-10-14 09:59:29 回复(5)
答案应该是A。因为在second()方法中的下面两句:
Value val = new Value();
v = val;
第一句在内存中创建了一个新的对象,也就是使用了一个新的地址空间。第二句让 v 这个对象将指针从 first() 方法中的 v 对象的地址空间指向了val 对象的地址空间。所以second()方法中的 v 对象和 val 对象使用的是同一个地址空间,其 i 属性应该相同,而first()方法中的 v 对象并没有改变自己指向的地址空间,其 i 属性应该是20
发表于 2015-12-15 17:02:45 回复(0)

该题考察的是java的参数传递,为按值传递。方法获得的是参数的拷贝,不管参数是基本数据类型还是引用类型。 如果参数类型为引用类型,比如该题,可以改变参数指向对象的值,但是不会改变参数指向的对象。在second方法中,v指向的值i变成20,但是v指向的对象还是原来的对象。即使在second方法中出现v=val赋值语句,表示的只是在second方法中v与val指向同一个对象,但是当方法结束,v指向的还是原来的对象,且原来的对象中的I值由15变成20.

发表于 2017-01-29 22:44:50 回复(0)
这题主要A和B有点迷惑。调用second方法时,当v.i= 20的时候,就把原来first中的v的属性i值改为20了。
然后,Value val = newValue( );v = val; v又指向new出来的新对象val的地址,i的默认值为15.
当执行完这个second方法后,v指向新对象就断开了。 而v.i的值依然为前面的20
所以在first方法最后 System.out.println(v.i)输出为20.
发表于 2016-08-15 16:22:01 回复(0)
看来了好多解释,似乎存在一个问题:java中到底是值传递还是引用传递?亦或者是两者都有(所说的基本类型值传递,其他类型引用传递)?参考这边博客,结论是:java中全部都是传递的副本,然后基本类型和引用类型有些区别,这样一来,至少对于这道题,我自己是理解通了 http://www.cnblogs.com/clara/archive/2011/09/17/2179493.html
发表于 2016-06-22 15:53:05 回复(0)
v.i在进入second后被赋值为20,然后它Value val =newValue( );新创建了一个Value 的对象val,而v = val;让v去指向这个val,此时的v已经和传进来的v对象没有关系了,故先输出15,0,然后出了second后,返回之前v.i在进入second后被赋值为20的值。
发表于 2016-04-22 21:29:51 回复(0)
春头像
详细请参考 http://blog.csdn.net/zzp_403184692/article/details/8184751
非常清晰
发表于 2015-10-26 17:01:13 回复(0)

second(v,i)

是把v这个引用复制一份传了过去

也就是在first方法中存在一个引用v1,在second方法中存在一个引用v2,两个引用都指向了同一个对象,即first方法中创建的对象。

second中创建了另外一个对象,并将v2指向了这个对象,并没有改变v1的指向,因此first方法中的v1依旧指向原来的对象。

发表于 2020-03-08 19:11:05 回复(0)
很多人会选b,我来说下,java在传递参数的时候,如果是传递引用,那么实际上方***复制该引用,方法使用的也是该引用的副本,所以我们可以通过该引用的副本来更改对象值,但是如果是将该引用指向另外一个对象(改变是这个引用副本),不会影响传递过来的引用,改变的仅仅是这个引用的副本。
编辑于 2019-06-06 01:51:47 回复(0)
选A,我原来也以为选B。即使是引用传递,参数传递的也是地址的拷贝,对成员变量的改变是有效的。
发表于 2015-10-29 10:02:30 回复(1)
发表于 2021-08-30 15:20:28 回复(1)
也就是说second中的 Value v只是原来v的一个别名,他对i得更改是可以更改原来的值,后来v指向了val也就跟原来的v没有关系了。
发表于 2015-11-25 20:45:49 回复(1)
亲测,15 0 20
发表于 2015-09-01 09:13:27 回复(0)
考查基本类型和引用类型作为形参传递,基本类型形参的改变不会影响实参,引用类型形参的改变会影响实参
发表于 2015-08-09 09:24:02 回复(0)
选B的同学们注意啦!java方法中引用传参相当于浅拷贝,所以在方法中改变引用的指向不影响原引用变量的指向。
发表于 2020-06-14 21:33:43 回复(0)
System.out.println(v.i+" "+i);中,v.i的值是指val中i的值,所以是15,i为0,但v.i=20,这个v改变的是first中v的指向对象中i的值变成了20,当second执行完,又继续执行first,v.i中的值已经被second中的v.i改变了,所以是20
发表于 2018-08-16 15:54:43 回复(0)
java中有值传递和引用传递,值传递的只有基本数据类型,其他基本上都是引用传递(类,接口,数组等)。引用传递本质上也是值传递,传递的是地址,按照值传递的规则,形参修改传过去的值对实参不可见,那么同样的道理,形参修改地址对实参不可见(比如形参指向别的对象),修改地址中的内容才对实参可见(只修改属性)。
发表于 2018-06-06 00:13:16 回复(0)