引言

最近刷牛客网上的题目时碰到不少有关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。关系整理一下如下图:

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语言的特性有关。通过一个图就可以知道上面程序的运行结果了。

由上图可知,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执行过程图如下:

对于基本数据类型 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]的值,真是不可思议。为什么会产生如此之结果。原来引用类型的按值传递,传递的是对象的地址。还是用图来解释一下。

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

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

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

经典笔试题 :

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按值传递和按引用传递就彻底懂了,答案和解析先匿了。

答案 : hello World
             hello world

原文

https://blog.csdn.net/u013309870/article/details/75499175

最新文章

  1. 学习C#线程
  2. 关于webpack编译scss文件
  3. 《Android深度探索HAL与驱动开发》第一章阅读心得
  4. linux ipv6临时地址
  5. JVM 常用配置
  6. C#语法基础和面向对象编程
  7. javascript 要注意的事项
  8. MySql 初次安装登陆
  9. CCF系列之矩阵(201512-5)
  10. PHP常见错误
  11. ADO.NET五大对象详解
  12. Docker搭建ElasticSearch+Redis+Logstash+Filebeat日志分析系统
  13. MySql 学习之路-Date函数
  14. 【C++ 实验六 继承与派生】
  15. Linux命令面试集
  16. dashboard使用与访问
  17. 项目实战03:Keepalived 实现高可用
  18. shell脚本中sqlite3命令查询数据库失败返回空,并将错误信息打印到标准错误输出
  19. 23、springboot与缓存(1)
  20. 转载免安装版mysql的配置

热门文章

  1. .prop() vs .attr()
  2. 项目中一次排序规则的改动,注意到js中map的遍历的顺序
  3. python 设计模式之模板方法模式
  4. latex运算符
  5. 亲历谷歌 Chrome 浏览器弹窗境外广告的解决方法(图) | 技术乐园
  6. 深入理解DefaultMessageListenerContainer
  7. 微信小程序之对象转化为数组
  8. antd ——按钮
  9. Tools - Nmap
  10. ASP.NET MVC4中的异步控制器