为什么说Java中只有值传递?
一.为什么说Java中只有值传递?
对于java中的参数传递方式中是否有引用传递这个话题,很多的人都认为Java中有引用传递,但是我个人的看法是,Java中只有值传递,没有引用传递。
那么关于对象的传递怎么解释呢?难道对象不是一个引用传递吗?
对于这一点我的看法是,对象的传递只不过是将对象的地址值传递到方法里,只要你不改变这个地址值,那他就指向原来的引用不会改变,但是你一旦改变了这个地址值,那么你就改变了他的实际引用。那归根到底还不是值传递吗?只不过我普通类型传递的是copy后的普通类型的值,我引用传递的是一个copy的地址值而已。
当然我在举例子的时候还是将他们分开:
实际的例子如下:
1.值传递
package com.cjm.functionparameter; /**
* @author 程嘉明
* @version 创建时间:2018/8/9 10:18
* 函数得值传递
*/
public class Valuetransmit {
public static void main(String[] args) {
int num=0;//定义一个值
System.out.println("在main中定义的值为:"+num);
fan(num);
System.out.println("在调用函数的值为:"+num);
}
public static void fan(int num){
System.out.println("###########进入函数###########");
System.out.println("实参为:"+num+"此时的值没有被改变!");
//修改函数的参数:
++num;
System.out.println("在函数中实参自增后的值为:"+num);
System.out.println("###########退出函数###########");
}
}

可以看出值传递是不会改变他本身的值。
所以Java中你就无法使用一个函数将两个变量的值交换。
尝试如下:
package com.cjm.functionparameter; /**
* @author 程嘉明
* @version 创建时间:2018/8/9 10:35
*/
public class ChangeValue {
public static void main(String[] args) {
//定义两个变量
int num1=0;
int num2=1;
System.out.println("未经过函数的交换的值为:"+"num1="+num1+"\tnum2="+num2);
change(num1,num2);
System.out.println("经过函数的交换后的值为:"+"num1="+num1+"\tnum2="+num2);
}
//设置一个”交换函数“
public static void change(int num1,int num2){
int temp=num1;
num1=num2;
num2=temp;
}
}

失败了,Java不能替我们完成这一项任务,但这无伤大雅,因为我们并不想交换两个变量的值就去定义一个函数,这实在是小题大做了。
2.杠精们的"引用传递"
那么首先我需要一个对象,来检测一下在函数中的对象是否和外面的对象相同。
package com.cjm.functionparameter; /**
* @author 程嘉明
* @version 创建时间:2018/8/9 10:53
* 对象的判断函数实参对象,和传递对象是否相同
*/
public class ObjectJudge {
public static void main(String[] args) {
A a=new A(0);
System.out.println("main函数中的对象的哈希值为:"+a.hashCode());
System.out.println();
fan(a);
}
public static void fan(A a){
System.out.println("函数中的对象的哈希值为:"+a.hashCode());
}
}
class A{
int num;
public A(int num) {
this.num = num;
}
}

可以看出这两个引用指向的对象的哈希值是一样的,那么也就是说这两个引用指向的是同一个对象。
那么也是说我们在函数对对象a的操作也会影响外面的对象。
来看下面的操作:
package com.cjm.functionparameter;
/**
* @author 程嘉明
* @version 创建时间:2018/8/9 10:53
* 对象的判断函数实参对象,和传递对象是否相同
*/
public class ObjectJudge {
public static void main(String[] args) {
A a=new A(0);
System.out.println("main函数中的对象的哈希值为:"+a.hashCode());
System.out.println("在main函数中的对象的num为:"+a.num);
System.out.println("##########函数开始##########");
fan(a);
System.out.println("##########函数之后##########");
System.out.println("在main函数中的对象的num为:"+a.num);
}
public static void fan(A a){
System.out.println("函数中的对象的哈希值为:"+a.hashCode());
a.num=10;
System.out.println("在函数中的对象的num为:"+a.num);
}
}
class A{
int num;
public A(int num) {
this.num = num;
}
}

那么我们现在再来修改一下,将函数中的对象修改为其他的引用会发生什么
package com.cjm.functionparameter;
/**
* @author 程嘉明
* @version 创建时间:2018/8/9 10:53
* 对象的判断函数实参对象,和传递对象是否相同
*/
public class ObjectJudge {
public static void main(String[] args) {
A a=new A(0);
System.out.println("main函数中的对象的哈希值为:"+a.hashCode());
System.out.println("在main函数中的对象的num为:"+a.num);
System.out.println("##########函数开始##########");
fan(a);
System.out.println("##########函数之后##########");
System.out.println("在main函数中的对象的num为:"+a.num);
}
public static void fan(A a){
System.out.println("为做改变前,函数中的对象的哈希值为:"+a.hashCode());
a=new A(0);
System.out.println("做了重新赋值后,函数中的对象的哈希值为:"+a.hashCode());
a.num=10;
System.out.println("在函数中的对象的num为:"+a.num);
}
}
class A{
int num;
public A(int num) {
this.num = num;
}
}
现在就是我们将 实参重新赋值了一个新的对象,那么我们可以发现a指向的对象已经改变,所以当我们对a进行操作时,main函数中的实参就不会改变了。
到这里我们可以总结出:Java中的参数传递就是值传递,只不过普通类型传递的是copy后的值,而对象传递的就是地址值,只要你不去改变地址值,那么你在函数中对对象的操作也会影响原来的对象。
那么现在又来了一个问题:
3.Java能不能交换两个对象呢?
直接上代码:
package com.cjm.functionparameter; /**
* @author 程嘉明
* @version 创建时间:2018/8/9 12:26
*/
public class ChangeObject {
public static void main(String[] args) {
A a1=new A(10);
A a2=new A(20);
System.out.println("在执行函数前:a1的值为:"+a1.num+"a2的值为:"+a2.num);
change(a1,a2);
System.out.println("在执行函数后:a1的值为:"+a1.num+"a2的值为:"+a2.num);
}
public static void change(A a1,A a2){
A temp=a1;
a1=a2;
a2=temp;
}
}

然而并没有交换。。。。。。
我们输出所有的哈希码:
package com.cjm.functionparameter; /**
* @author 程嘉明
* @version 创建时间:2018/8/9 12:26
*/
public class ChangeObject {
public static void main(String[] args) {
A a1=new A(10);
A a2=new A(20);
System.out.println("在执行函数前:a1的值为:"+a1.num+"a2的值为:"+a2.num);
System.out.println("main函数中的a1的哈希码为:"+a1.hashCode()+"a2的哈希码为:"+a2.hashCode());
System.out.println("############执行函数#############");
System.out.println();
change(a1,a2);
System.out.println("在执行函数后:a1的值为:"+a1.num+"a2的值为:"+a2.num);
System.out.println("############函数之后#############");
}
public static void change(A a1,A a2){
System.out.println("函数刚开始时的a1的哈希码为:"+a1.hashCode()+"a2的哈希码为:"+a2.hashCode());
A temp=a1;
a1=a2;
a2=temp;
System.out.println("函数中的a1的哈希码为:"+a1.hashCode()+"a2的哈希码为:"+a2.hashCode());
}
}

似乎没有问题:因为在函数中a1和a2的地址值是改变了,但是这是一个地址值,你修改了他有什么作用呢?
图解如下:
开始时:

在函数中进行交换:

那么此时main函数中的对象会交换吗?当然不会!所以还是那一句话:
到这里我们可以总结出:Java中的参数传递就是值传递,只不过普通类型传递的是copy后的值,而对象传递的就是地址值,只要你不去改变地址值,那么你在函数中对对象的操作也会影响原来的对象。
4.针对一个特殊类String类
为什么说这个String特殊呢?
因为:面试题里面都是拿他做例子所以他特殊(#手动滑稽)
当然不是了,主要是因为String是final类不能在对象上去修改,只能new一个新的对象。
所以看看下面的代码你就知道我的意思了:

当你的参数拼接后其实已经改变了你这个对象的引用。而你的形参的类型是final的这也就代表着你不能改变他的引用对像。
讲这个似乎对我们这个没有帮助,那么我们来看看下面的代码:
package com.cjm.functionparameter; /**
* @author 程嘉明
* @version 创建时间:2018/8/9 14:08
* String类型是否能够在拼接符的作用下不改变对象
*/
public class StringAdd {
public static void main(String[] args) {
String str="101010";
System.out.println("在没有进入函数之前String的对象的哈希码为:"+str.hashCode());
stringChange(str);
System.out.println("str经过函数的值为:");
System.out.println(str);
}
public static void stringChange(String str){
System.out.println("进入函数后没有修改String之前的Str的哈希码为:"+str.hashCode());
str+="aaaa";
System.out.println("进入函数后修改String之后的Str的哈希码为:"+str.hashCode());
}
}

在修改时我们的值没有发生改变。
就是拼接后你的String对象已经改变,接下来你所做的就与main函数里的str变量没有关系了。
为什么说Java中只有值传递?的更多相关文章
- Java中的值传递
1.先比较下字符串的比较 == 代表全等于 值和地址(存放地址) 全部相等于. equals 值等于== 和 equals的区别 列如下面的 如果name1==name2是等于的 然而name1==n ...
- 为什么说Java中只有值传递
本文转载自公众号 Hollis 对于初学者来说,要想把这个问题回答正确,是比较难的.在第二天整理答案的时候,我发现我竟然无法通过简单的语言把这个事情描述的很容易理解,遗憾的是,我也没有在网上找到哪篇文 ...
- 一道笔试题来理顺Java中的值传递和引用传递
题目如下: private static void change(StringBuffer str11, StringBuffer str12) { str12 = str11; str11 = ...
- java中的值传递和引用传递有什么区别呀?
值传递: (形式参数类型是基本数据类型和String):方法调用时,实际参数把它的值传递给对应的形式参数,形式参数只是用实际参数的值初始化自己的存储单元内容,是两个不同的存储单元,所以方法执行中形式参 ...
- 为什么说Java中只有值传递(转载)
出处:https://www.hollischuang.com/archives/2275 关于这个问题,在StackOverflow上也引发过广泛的讨论,看来很多程序员对于这个问题的理解都不尽相同, ...
- 为什么说Java中只有值传递----说服自己
在开始深入讲解之前,有必要纠正一下大家以前的那些错误看法了.如果你有以下想法,那么你有必要好好阅读本文. 错误理解一:值传递和引用传递,区分的条件是传递的内容,如果是个值,就是值传递.如果是个引用,就 ...
- Java 中的值传递和引用传递问题
Java 中的值传递和引用传递问题 public class Operation { int data = 50; void change(int data) { data = data + 100; ...
- Java中只有值传递,(及值传递与引用传递详解)
首先呢,我们来说一下值传递与引用传递的区别(这两个玩意儿实在调用函数的时候提到的) 比如说 code( a) code( int a ) code(a)是调用函数,a是我们原本函数的一个值类型,然后使 ...
- 为什么说 Java 中只有值传递?
对于初学者来说,要想把这个问题回答正确,是比较难的.在第二天整理答案的时候,我发现我竟然无法通过简单的语言把这个事情描述的很容易理解,遗憾的是,我也没有在网上找到哪篇文章可以把这个事情讲解的通俗易懂. ...
随机推荐
- POJ - 题解sol[暂停更新]
初期:一.基本算法: (1)枚举. (poj1753,poj2965) poj1753 话说我用高斯消元过了这题... poj2965 巧了,用高斯消元01矩阵更快(l o l). (2)贪心(poj ...
- java关键字总结
static: 用来修饰成员变量和成员方法,也可以形成静态static代码块,可以形成静态内部类,也可以用于静态导包. 1.静态方法中不能用this和super关键字,不能直接访问所属类的实例变量和实 ...
- SpringBoot的日志
1.日志框架小张:开发一个大型系统:1.System.out.pringtln("");将关键数据打印在控制台:去掉?写在一个文件?2.框架来记录系统的一些运行信息:日志:zhan ...
- matlab画图变粗脚本
http://blog.sina.com.cn/s/blog_708637950100uag0.html figure_FontSize=18;set(get(gca,'XLabel'),'FontS ...
- Ubuntu16.10下mysql5.7的安装及远程访问配置
如何安装mysql 1.sudo apt-get update,如果很慢或者失败,需要在软件和更新中选择最佳服务器,勾选所有互联网下载选项及去掉其他软件所有勾选项 2.sudo apt-get upg ...
- html盒子水平和垂直居中
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- POJ 1840 Eqs 解方程式, 水题 难度:0
题目 http://poj.org/problem?id=1840 题意 给 与数组a[5],其中-50<=a[i]<=50,0<=i<5,求有多少组不同的x[5],使得a[0 ...
- 五. Python基础(5)--语法
五. Python基础(5)--语法 1 ● break结束的是它所在的循环体, continue是让它所在的循环体继续循环 # 打印: 1 10 2 10 3 10 4 10 5 10 6 10 7 ...
- 四. Python基础(4)--语法
四. Python基础(4)--语法 1 ● 比较几种实现循环的代码 i = 1 sum = 0 while i <= 10: # 循环10-1+1=10次 sum += i i ...
- 一个在linxu自动切换ip的脚本
最近的爬虫是在linux下运行的,使用的是云立方的代理服务器,需要自动切换一下ip. #!/bin/bash# coding:utf8 aa="sources.list" #主流程 ...