java装箱引用传递_Java面试中的值传递与引用传递

一、前言

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

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

二、常见例子

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

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;

2、封装类型参数

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=after和p.num=1 。

这里我们可以看到 changeProduct(p); 该语句传递的是p内存中存储的地址的副本,该地址就是new Product();的地址。在changeProduct方法中对p地址的副本指向的值进行操作,由于副本地址和原地址一样,所以相当于最终p地址指向的值也会发生变化。所以这里的changeProduct方法能改变实参。

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

private static void changeProduct(Product p) {

p = new Product();//添加这条语句,相当于P的地址变成new Product()新对象的地址,不是主函数中的对象的地址

p.setProName("after");

p.setNum(1);

}

这里添加的这条语句 改变了副本的地址,导致副本指向新对象的地址,因此变成对新对象的操作,不影响主函数中的原对象,最终输出结果是:p.proName=before和p.num=0 。

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

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

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";

}

}

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

最终输出结果是: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”.

4、常见面试题

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数组的值发送变化。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值