java按值传递和按引用传递_深入理解--Java按值传递和按引用传递

引言

最近刷上的题目时碰到不少有关Java按值传递和按引用传递的问题,这种题目就是坑呀,在做错了n次之后,查找了多方资料进行总结既可以让自己在总结中得到提高,又可以让其他人少走弯路。何乐而不为?

Java按值传递和按引用传递

首先问一句:Is Java “pass-by-reference” or “pass-by-value”? Java到底是按值传递还是按引用传递的呢?国外的网站上关于这个问题的讨论非常之多。官方答案:The Java Spec says that everything in Java is pass-by-value. There is no such thing as “pass-by-reference” in Java. 官方的说法是在java中只有按值传递,并没有所谓的按引用传递。

基本数据类型的按值传递

java数据类型可以分为两大类:基本类型(primitive types)和引用类型(reference types)。primitive types 包括boolean类型以及数值类型(numeric types)。numeric types又分为整型(integer types)和浮点型(floating-point type)。整型有5种:byte short int long char(char本质上是一种特殊的int)。浮点类型有float和double。关系整理一下如下图:

7f3cd54f0e900fe0b387ef6912fa1139.png

例1

public class Swap {

public static void main(String[] args) {

int x = 10;

int y = 20;

swap(x, y);

System.out.println("x(2) = " + x);

System.out.println("y(2) = " + y);

}

public static void swap(int x, int y) {

int temp = x;

x = y;

y = temp;

System.out.println("x(1) = " + x);

System.out.println("y(1) = " + y);

}

}

/*输出

x(1) = 20

y(1) = 10

x(2) = 10

y(2) = 20

*/

上面程序main函数调用swap函数来交换 x,y的值,然而调用函数之后发现main中x,y的值并未交换。包括在Java api中找不到一个可以交换两个变量的方法。这与Java语言的特性有关。通过一个图就可以知道上面程序的运行结果了。

0d96afb080a49689fb578c475ea2f6b4.png

由上图可知,main函数中的x,y和swap函数中的x,y分别存放在不同的区域,在main中调用swap函数的时候,会将main中的x,y的值赋给swap中的x,y。当swap函数中对x,y交换时只是对swap帧中的x,y做交换,并不会改变main中的x,y。所以当函数返回时main中的x,y并不会改变。swap执行过程图如下:

9a6e2e6744fc9aee7791c55db0c81300.png

对于基本数据类型 short int long float double char byte boolean这八种按值传递调用函数并不会改变在原函数中的值。

引用数据类型的按值传递

引用数据数据类型分为三种:①接口 ②类 ③数组对于引用数据类型的按值传递先给出一个实例对比实例进行分析。

例2

public static void main(String[] args) {

int []a={10,20};

System.out.println("a[0] :"a[0]+"a[1] : "+a[1]);//a[0]=10,a[1]=20;

swap(a, 0, 1);

System.out.println("a[0] :"a[0]+"a[1] : "+a[1]);//a[0]=20,a[1]=10;

}

public static void swap(int []a,int i,int j){

int temp=a[i];

a[i]=a[j];

a[j]=temp;

System.out.println("a[0] :"a[0]+"a[1] : "+a[1]);//a[0]=20,a[1]=10;

}

//输出

/*a[0]=10 a[1]=20

a[0]=20 a[1]=10

a[0]=20 a[1]=10

*/

运行程序后发现,swap函数对a[0] ,a[1]的操作竟然影响到了main函数中的a[0] ,a[1]的值,真是不可思议。为什么会产生如此之结果。原来引用类型的按值传递,传递的是对象的地址。还是用图来解释一下。

89bb8c7560d0b51950c540324ba34e93.png

由图可以看出在swap中仅仅是得到了数组的地址,并没有对数组的元素进行复制,在swap中对数组的操作是直接对main函数中数组的操作,因此swap函数返回后main函数中的a[0] ,a[1]的值发生交换。

数组、类、接口按值传递的时候都是传递对象的地址。再来看一个比较复杂的实例。

例3

public class Main{

public static void main(String[] args){

Foo f = new Foo("f");

changeReference(f); // It won't change the reference!

modifyReference(f); // It will modify the object that the reference variable "f" refers to!

}

public static void changeReference(Foo a){

Foo b = new Foo("b");

a = b;

}

public static void modifyReference(Foo c){

c.setAttribute("c");

}

}

①Foo f = new Foo(“f”);

f40f7bdf134d698193af45b6f380b65c.png

②public static void changeReference(Foo a)

90be628bc0927d6265462e7ae9717a1e.png

③changeReference(f);

dd8972c8f37e56fcc066d9e9b6797de1.png

④Foo b = new Foo(“b”);

06c6e53289f22f3425fb5d151d267e14.png

⑤a = b

bc964efd2b3dc5aa5f75d01dc6333be7.png

7ec041e4cf3486fe2b2b29d75aee3d52.png

⑥c.setAttribute(“c”);

49f218f0649b8a1eac79be87658af36f.png

经典笔试题目

试题1

public class Demo {

public static void main(String[] args) {

//demo1

String str=new String("hello");

char []chs={'w','o','r','l','d'};

change(str, chs);

System.out.println(str+" "+new String(chs));

//-------------------------------------------------

//demo2

StringBuffer sb=new StringBuffer("hello");

change(sb);

System.out.println(sb);

}

public static void change(StringBuffer sb)

{

sb.append(" world");

// sb.deleteCharAt(0);

}

public static void change(String str,char[]chs)

{

str.replace('h', 'H');

chs[0]='W';

}

}

上面程序段demo1和demo2分别输出什么,这里涉及到String特性,这道题目会做了,Java按值传递和按引用传递就彻底懂了,答案和解析先匿了。

试题2

public class foo {

public static void main(String sgf[]) {

StringBuffer a=new StringBuffer(“A”);

StringBuffer b=new StringBuffer(“B”);

operate(a,b);

System.out.println(a+”.”+b);

}

static void operate(StringBuffer x,StringBuffer y) {

x.append(y);

y=x;

}

}

参考文献

1.https://stackoverflow.com/questions/40480/is-java-pass-by-reference-or-pass-by-value

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值