Java面试题21——参数传递中的值传递

参数传递中的值传递

当一个对象被当作参数传递到一个方法后,在此方法内可以改变这个对象的属性,那么这里到底是值传递还是引用传递?

**答:是值传递。**Java 语言的参数传递只有值传递。当一个实例对象作为参数被传递到方法中时,参数的值就是该对象的引用的一个副本。指向同一个对象,对象的内容可以在被调用的方法内改变,但对象的引用(不是引用的副本) 是永远不会改变的。

​ 但是String和Integer这些类型的内容被调用的方法改变,原对象的值不会改变。因为String是不变类,任何的操作都不会影响已经创建好的值。而Integer和其他包装类也有这个特点。看下面这三个例子,可以更好地理解参数传递中的值传递。

例1:普通的类
package demo;
public class Cat {
    private String name;
    private int age;
    private String gender;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getGender() {
        return gender;
    }
    public void setGender(String gender) {
        this.gender = gender;
    }
    public static void main(String[] args) {
        Cat cat = new Cat();
        cat.setName("小白");
        cat.setAge(18);
        cat.setGender("母");
        System.out.println(cat.name);
        cat.change(cat);
        System.out.println(cat.name);
        Cat cat1 = cat;
        cat1.setName("小美");
        System.out.println(cat1.name);
        System.out.println(cat.name);
    }
    public void change(Cat cat) {
        cat.name = "小花";
    }
}

//输出的值为
小白
小花
小美
小美
使用change方法可以修改cat对象的值,因为该方法将cat对象的引用地址传给了参数cat,然后参数cat修改其对应的堆空间中的值,而调用change方法的cat对象指向的也是这个堆空间,所以此修改会影响到原对象。
例2:string类

public class StrTest {
    public static void main(String[] args) {
   String str = new String("laowang");
   changeString(str);
    System.out.println(str);
   }
     public static void changeSting(String str) {
        str.replace("x","d");
    }}
 //输出的值为
 laowang
 
 使用change方法,复制一份str对象的引用给参数str,然后str使用replace方法进行一些修改,但string类对象是不可修改的,所以此番修改会重新创建一个string对象,修改是在新创建的对象上进行,不影响原对象。这个例子很好地说明string的不可变性
 
 要警惕另一种情况,例子如下:
 public class StrTest {
    public static void main(String[] args) {
   String str = new String("laowang");
   changeString(str);
    System.out.println(str);
   }
     public static void changeSting(String str) {
        str="xiaowang"
    }}
    
//结果如下:
laowang

虽然结果一样,但原因并不是string的不可变性。是因为调用方法时,计算参数string的值(可以理解为“laowang”这个字符串对象在内存中的地址),拷贝给参数str,参数str虽然拿到了原来laowang字符串对象的引用(即str的值等于string的值,也即hello的地址),但是立马给这个参数重新赋值,也就是创建了一个新的字符串,把这个字符串的地址赋给了参数str,这个时候str参数已经跟“laowang”字符串没有任何关系了,str不再指向"laowang",改指向xiaowang了,但是这个过程中laowang自身以及laowang在内存中的地址没有任何变化.


//还有另外一种情况
//示例1:对象类型
public class PassReferByValue  
{  
    String a = "123";  
    public static void test(PassReferByValue test)  
    {  
        test.a = "abc";  
    }  
  
    public static void main(String[] args)  
    {  
        PassReferByValue test = new PassReferByValue();  
        System.out.println("对象的数据的初始值是:" + test.a); //123 
          
        test(test);  
        System.out.println("通过调用test方法修改对象的数据的值之后:" + test.a); //abc  
          
    }  
} 
在方法中使用类实例改变全局变量的值,由于该全局变量的String类型,为“123”,该对象不会被改变,但其会被覆盖,当使用类实例.属性名访问时,访问到的是修改后的值。因为该值在方法之外也会生效。这个和string类型的不可变性无关。
例3:Integer类和stringBuilder类
import java.util.Iterator;

/**
 * Created by lili on 15/9/24.
 */
public class TestNew {
    public static void main(String args[]){
        Integer i1 = 10;
        Integer i2 = 20;
        System.out.println(i1   + "   " + i2);
        change(i1,i2);
        System.out.println(i1   + "   " + i2);

        StringBuilder sb1 = new StringBuilder("sb1");
        StringBuilder sb2 = new StringBuilder("sb2");
        System.out.println(sb1   + "   " + sb2);
        change(sb1,sb2);
        System.out.println(sb1   + "   " + sb2);

    }

    public static void change(Integer i1, Integer i2){
        i1 = 100;
        i2 = 200;
    }
    public static void change(StringBuilder i1, StringBuilder i2){
        i1.append("sbsbsb1");
        i2.append("sbsbsb2");
    }
}
//输出结果为以下所示,可以知道只有stringBuilder才为引用传递。Integer也是不可变类。
10   20
10   20
sb1   sb2
sb1sbsbsb1   sb2sbsbsb2

下面再来看一个数组的例子

public static void main(String[] args) {
    int[] arr = {2, 3, 4, 8};
    change(arr);
    System.out.println(arr[2]);
}
private static void change(int[] arr) {
    for (int i = 0; i < arr.length; i++) {
        if (i % 2 == 0) {
            arr[i] *= i;
        }
    }
}

输出的值是多少呢?
数组作为参数传递到change方法中,传递的为引用地址,方法的操作可以对原数组进行修改,故数组里面的值会变化,最后输出的值为8.

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值