JAVA中的值传递和引用传递问题
这是个老生常谈的问题了,引起过无数争论,但可以说一直没有一个令人满意的回答。
有人总结过:
- 对象是按引用传递的
- Java 应用程序有且仅有的一种参数传递机制,即按值传递
- 按值传递意味着当将一个参数传递给一个函数时,函数接收的是原始值的一个副本
- 按引用传递意味着当将一个参数传递给一个函数时,函数接收的是原始值的内存地址,而不是值的副本
简单总结:
- 对象就是传引用(引用地址的拷贝,实质也是传值)
- 原始类型就是传值
- String等immutable类型因为没有提供自身修改的函数,每次操作都是新生成一个对象,所以要特殊对待。可以认为是传值。
一个小问题
在开源中国看到这样一则问题:
https://www.oschina.net/question/2507499_2244027,其中的变量a前后的输出是什么?
我答错了,我认为传入function的就是main函数中的a,在function中修改了a的地址,因此回到主函数后,a的地址已经变成了function中所赋予的a2的地址,因此经过function处理后a的值已经改变了。 但结果并不是,因为我忽略了Java的基础知识点之一:Java中传参都是值传递,如果是基本类型,就是对值的拷贝,如果是对象,就是对引用地址的拷贝。
基本类型的传递
以下是处理类Porcess,代码应该已经能够自解释了。function1是将传参a变成2,function2是初始化int b,赋值为5,然后将b赋值给a:
public class Process {
public void function1(int a) {
a = 2;
}
public void function2(int a) {
int b = 5;
a = b;
}
}
我们继续看测试类TestPrimitive:
public class TestPrimitive {
public static void main(String[] args) {
Process process = new Process();
int age = 18;
System.out.println(age);
process.function1(age);
System.out.println(age);
}
}
经过function1处理后,结果是:
18
18
修改测试类,经过function2处理后,结果是:
18
18
结论:基本类型传参,对传参进行修改,不影响原本参数的值。
对象类型传参
以下是处理类Porcess,function3,将参数car的颜色设置成blue。function4,新建了car2,将car2赋值给了参数car。
public class Process {
public void function3(Car car) {
car.setColor("blue");
}
public void function4(Car car) {
Car car2 = new Car("black");
car = car2;
car.setColor("orange");
}
}
我们继续看测试类TestReference
public class TestReference {
public static void main(String[] args) {
Process process = new Process();
Car car = new Car("red");
System.out.println(car);
process.function3(car);
System.out.println(car);
}
}
结果是在经过function3的处理后,输出结果是:
Car{color='red'}
Car{color='blue'}
修改测试类,在经过function4的处理后:
Car{color='red'}
Car{color='red'}
结论: 对象类型的传参,直接调用传参set方法,可以对原本参数进行修改。如果修改传参的指向地址,调用传参的set方法,无法对原本参数的值进行修改。
综上所述,基本类型的传参,在方法内部是值拷贝,有一个新的局部变量得到这个值,对这个局部变量的修改不影响原来的参数。对象类型的传参,传递的是堆上的地址,在方法内部是有一个新的局部变量得到引用地址的拷贝,对该局部变量的操作,影响的是同一块地址,因此原本的参数也会受影响,反之,若修改局部变量的引用地址,则不会对原本的参数产生任何可能的影响。
JAVA中的值传递和引用传递问题的更多相关文章
- Does Java pass by reference or pass by value?(Java是值传递还是引用传递) - 总结
这个话题一直是Java程序员的一个热议话题,争论不断,但是不论是你百度搜也好还是去看官方的文档中所标明的也好,得到的都只有一个结论:Java只有值传递. 在这里就不贴代码细致解释了,让我们来看看一些论 ...
- Java中值传递和引用传递的概念
很多书中都提到了在Java中只存在值传递,但是今天在一个NanoHTTPD的源码中看到这样一段: if (qmi >= 0) { decodeParms(uri.substring(qmi + ...
- Java中引用类型变量,对象,值类型,值传递,引用传递 区别与定义
一.Java中什么叫做引用类型变量?引用:就是按内存地址查询 比如:String s = new String();这个其实是在栈内存里分配一块内存空间为s,在堆内存里new了一个Stri ...
- java中值传递和引用传递
最近工作中使用到了值传递和引用传递,但是有点懵,现在看了下面的文章后清晰多了.一下是文章(网摘) 1:按值传递是什么 指的是在方法调用时,传递的参数是按值的拷贝传递.示例如下: public clas ...
- Java中的值传递和引用传递
这几天一直再纠结这个问题,今天看了这篇文章有点思路了,这跟C++里函数参数为引用.指针还是有很大区别. 当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里 ...
- java中方法的参数传递机制(值传递还是引用传递)
看到一个java面试题: 问:当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递? 答:是值传递.Java 编程语言只有值传递参 ...
- Java中传参的值传递和引用传递问题(转)
今天遇到了一个java程序,需要用参数来返回值(虽然最后用另一种方法实现了),在网上看到这样一篇文章,很受启发. 本文章来自于http://hi.baidu.com/xzhilie/blog/item ...
- 一道笔试题来理顺Java中的值传递和引用传递
题目如下: private static void change(StringBuffer str11, StringBuffer str12) { str12 = str11; str11 = ...
- java中的值传递和引用传递有什么区别呀?
值传递: (形式参数类型是基本数据类型和String):方法调用时,实际参数把它的值传递给对应的形式参数,形式参数只是用实际参数的值初始化自己的存储单元内容,是两个不同的存储单元,所以方法执行中形式参 ...
- Java中的值传递与引用传递
1.基本类型和引用类型在内存中的保存 Java中数据类型分为两大类,基本类型和对象类型.相应的,变量也有两种类型:基本类型和引用类型. 基本类型的变量保存原始值,即它代表的值就是数值本身: 而引用类型 ...
随机推荐
- PHP实现数组中每个字符出现次数最多的,并且如果两个字符出现相同,则在前面的先输出功能
$arr = ['a', 'b', 'a', 'e', 'g', 'g', 'a']; $count_per_values = array_count_values($arr); $res = []; ...
- [摘录] 图灵机与lambda演算的关系
在阅读函数式编程相关资料时,看到如下一段话.感觉说的很好,可以帮助我这种学渣一点点的建立起整个知识体系. 以下片段,摘抄自豆瓣网友 赛义甫 的豆列 “逻辑与计算” 中的一段介绍. 莱布尼兹曾经有两个梦 ...
- 腾讯TBS加载网页无法自适应记录
1. 所遇到的问题 webview加载指定网页无法实现自适应,之前在加载重构一个网页的时候,其实也遇到这种问题,然后就有了下面的一下步骤 WebSettings webSettings = view ...
- python框架之Django(14)-rest_framework模块
APIView django原生View post请求 from django.shortcuts import render, HttpResponse from django import vie ...
- Number 强制类型转换 int 强制转换整型 float 强制转换浮点型 complex 强制转换成复数 bool 强制转换成布尔类型,结果只有两种,要么True 要么 False """bool 可以转换所有的数据类型 everything"""
# ###Number 强制类型转换 var1 = 5 var2 = 4.85 var3 = True var3_2 = False var4 = 3+9j var5 = "888777&q ...
- 解决mysql大小写敏感问题
先在服务中 找到 my.min 文件 在 [mysqld] 下面添加一行: lower_case_table_names = 0 其中 0:区分大小写,1:不区分大小写 设置好后 需要重启服务 然 ...
- 使用rander() 将后台的数据传递到前台界面显示出来
1.创建templates文件夹 2.在该文件夹内创建html界面a.html 3.views.py: def a(request): love='iloveyou' return render(re ...
- html5 javascript 新增加的高级选择器更精准更实用
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8&qu ...
- GO数组
Array(数组) 数组是同一种数据类型元素的集合. 在Go语言中,数组从声明时就确定,使用时可以修改数组成员,但是数组大小不可变化. 数组定义: var 数组变量名 [元素数量]T ]int //定 ...
- jQuery 查找元素2
jQuery 查找元素2 :first <ul> <li>list item 1</li> <li>list item 2</li> < ...