Java面试中的值传递与引用传递

1、前言

Java是值传递的,对基本型变量而言的,传递的是该变量的一个副本,改变副本不影响原变量。对于对象型变量而言的,传递的是该对象地址的一个副本,,并非原对象自己 ,这里也有人说是引用传递。因为副本的地址和原对象地址一致,所以对副本的值进行操做时,会同步改变原对象值。html

可是一旦副本的地址被改变,副本的值的操做则不会影响原对象地址。(重点)java

2、常见例子

一、基本类型参数的值传递

public class Test {
    public static void main(String[] args) {
        int num = 0 ;
        changeNum(num);
        System.out.println("num="+num);
    }
 
    private static void changeNum(int num) {
        num = 1;
    }
}

最终输出结果是:num=0面试

由于这里 changeNum(num);语句中的num传递的是num的副本,也就是形参,因此当副本变为1,对实参原对象不影响,原对象仍是num=0;数组

 

二、封装类型参数

public class Test {
    public static void main(String[] args) {
        Product p = new Product();
        p.setProName("before");
        p.setNum(0);
        changeProduct(p);
        System.out.println("p.proName="+p.getProName());
        System.out.println("p.num="+p.getNum());
    }
 
    private static void changeProduct(Product p) {
        p.setProName("after");
        p.setNum(1);
    }
}
 
class Product {
    private int num;
    private String proName;
 
    public int getNum() {
        return num;
    }
 
    public void setNum(int num) {
        this.num = num;
    }
 
    public String getProName() {
        return proName;
    }
 
    public void setProName(String proName) {
        this.proName = proName;
    }
}

最终输出结果是:p.proName=afterp.num=1函数

这里咱们能够看到 changeProduct(p); 该语句传递的是p内存中存储的地址的副本,该地址就是new Product();的地址。在changeProduct方法中对p地址的副本指向的值进行操做,因为副本地址和原地址同样,因此至关于最终p地址指向的值也会发生变化。因此这里的changeProduct方法能改变实参。this

 

可是存在如下特殊状况,就是前言说的一旦副本的地址被改变。咱们再 changeProduct() 方法中添加一条语句;spa

private static void changeProduct(Product p) {
    p = new Product();//添加这条语句,至关于P的地址变成new Product()新对象的地址,不是主函数中的对象的地址
    p.setProName("after");
    p.setNum(1);
}

这里添加的这条语句 改变了副本的地址,致使副本指向新对象的地址,所以变成对新对象的操做,不影响主函数中的原对象,最终输出结果是:p.proName=beforep.num=0.net

 

三、容易忽略的特殊类型String

首先要清楚一点,这种说法不正确:String str = "java",这就至关于String str = new String("java"),这是建立一个新的String的过程,不仅仅是赋值的过程。code

public class Test {
    public static void main(String[] args) {
        String str = "ab";
        changeString(str);
        System.out.println("str="+str);
    }
 
    private static void changeString(String str) {
        str = "cd";
    }
}

猜猜这里最终结果是什么?htm

最终输出结果是:str=ab 。(没猜对的说明上面第二点还没理解清楚)

解析:

str1 = "cd"
str2 = new String("cd");
System.out.println(str1 == str2); // false
说明str = "cd";不能被解释为以下:str = new String("cd");
这里之因此最终显示结果是“ad”,是由于main中的str的地址是常量池“ad”的地址,而在str = "cd"说明此时str的地址变成常量池“cd”的地址,地址改变,对实参原来的str无影响,因此最终输出的仍是“ad”.

 

四、常见面试题

public class Example {
    String str = new String("good");
    char[] ch = { 'a', 'b', 'c' };
 
    public static void main(String args[]) {
        Example ex = new Example();
        ex.change(ex.str, ex.ch);
        System.out.print(ex.str + " and ");
        System.out.print(ex.ch);
    }
 
   public void change(String str, char ch[])      
   {
        str = "test ok";
        ch[0] = 'g';
    }
}

从以下4个选项选出最终输出结果

A 、 good and abc
B 、 good and gbc
C 、 test ok and abc
D 、 test ok and gbc

正确答案: B

解析:

ex.str如第3点所说的,其传递的地址副本在change方法中被改变,所以不影响原地址的对象,因此ex.str不变;

ch数组是对象,数组的父类也是Object。传递的是数组地址的副本,所以在change中副本地址没改变,至关于对原对象进行操做,因此ch数组的值发送变化。

 

 

参考资料:https://blog.csdn.net/party3/article/details/78648186

                https://www.cnblogs.com/boboooo/p/9066831.html

相关文章
相关标签/搜索