(重要)java都是值传递,与对象形参所指向的对象改变,其实参所指向的对象也相应改变并不矛盾(2011年9.30日一天写的两个程序的总结结果)...
1.0建立二叉树的代码,在java中必须创建二叉树的方法必须用返回值,因为不存在c语言中的引用传递,在java中只有值传递 代码1为正确,代码2(没有使用返回值)为错误。那么为什么之前的例子中将对象作为参数时,对对象内容的更改还是正确的,也没有使用返回值,二者看似矛盾,其实并不矛盾,以前都没有理解到这个本质,本质就是参数中,确实是有一个临时变量,交换形式对象参数,实际的参数不会改变,但是改变形式参数的引用所指向的内容,即这个对象本身改变,其实参所引用的对象也是同一个对象,当然该对象也会发生变化,因为实参和形参引用的都是同一个对象,只不过是两份地址的拷贝。
即便是c语言如果不用引用传递-&,就是说用指针,也需要用返回值的方法建立二叉树,才能将已建立好的二叉树头指针返回给打印函数的参数。当然java中可以采用对私有变量等操作,即不不使用参数传递,而仅仅是创建函数和打印函数共同操作的是同一个变量也可以吧,估计递归就不好用了,这个怎么做没去想!~~~
错误代码:这个时候打印出来的树的节点为空,printInOrder(tree1)输出节点为空:
import java.util.*; class TNode{int data; TNode lchild; TNode rchild; TNode(int a) { data=a; lchild=null; rchild=null; }} public class BTree { static TNode root=new TNode(1); static void creatTree(TNode root) { Scanner in=new Scanner(System.in);int a=in.nextInt();if(a==0){ root=null;return; } else{ root=new TNode(a); creatTree(root.lchild); creatTree(root.rchild); } }static void printInOrder(TNode root){if(root==null)return;else{ System.out.print(root.data); printInOrder(root.lchild); printInOrder(root.rchild); } } public static void main(String[] args) {// TODO Auto-generated method stub creatTree(root); printInOrder(root); } }
正确代码:
import java.util.Scanner; class Tode{ int data; Tode lchild; Tode rchild; Tode(int a) { data=a; lchild=null; rchild=null; } } public class TREE{ static Tode root=null; static Tode creatTree(Tode root) { Scanner in=new Scanner(System.in); int a=in.nextInt(); if(a==0){ return null ; } else{ root=new Tode(a); root.lchild=creatTree(root.lchild); root.rchild=creatTree(root.rchild); return root; } } static void printInOrder(Tode root){ if(root==null) return; else{ System.out.print(root.data); printInOrder(root.lchild); printInOrder(root.rchild); } } public static void main(String[] args) { // TODO Auto-generated method stub Tode tree1=creatTree(root); printInOrder(tree1); } }
1.1、疑惑解决了,原来认为方法中传入一个对象的话(数组也行),如果方法内部对这个对象的内部参数进行了更改,则其实就是对外部的这个静态对象也进行了修改,相当于c++中的真正的引用传递吧,但是传入的是整型等普通类型,则还是不能够更改,可以见下面的实例。如果传入的对象是数组的话,也可以更改,因为java中数组也是对象~,其实也不是 因为是对引用所指向的内容进行了修改,引用可以有多个,但是引用所指向的内容只有一份!!!!!!
以下程序的输出结果是0 1 2
import java.util.*; class node{int data; node lchild; node rchild;public node(int a){ data=a; lchild=null; rchild=null; }} public class testclass2 { public void changeroot(node root){ node newnode1=new node(1); node newnode2=new node(2); root.lchild=newnode1; root.rchild=newnode2; } public void print(node root){ System.out.println(root.data); System.out.print(root.lchild.data); System.out.print(root.rchild.data); }public static void main(String[] args){ node root=new node(0); testclass2 dd=new testclass2(); dd.changeroot(root); dd.print(root); } }
1.2、下面是另一个例子,在算法例子中也常用到因为是 对引用所指向的内容进行了修改,引用可以有多个,但是引用所指向的内容只有一份!!!!!!
以下程序输出结果是2 4 3 4
void diguiInorderTraverse(node root){ root.lchild }解释说的通了,传入root,对root修改,其实就相当于 class A{int b=2;}public class Testclass {static A a=new A();static void changeA(A a){ a.b=3; }static int b=4;static void changeB(int b){ b=5; }public static void main(String[] args) {// TODO Auto-generated method stub System.out.println(a.b); System.out.println(b); changeA(a); changeB(b); System.out.println(a.b); System.out.println(b); }}
1.3、也就是说root对象确实分配了一个临时对象,传入的都是地址的引用,所以对这个参数的改变,对引用所指向的内容进行了修改,引用可以有多个,但是引用所指向的内容只有一份!!!!!!
我看了一些引用调用和值调用的定义,很多人都把是传递值,还是传递地址?是改变参数自身内容,还是改变参数所指向的地址中的内容作为区别这两种调用的标志。这很不恰当,这些说法很容易让我们联想到Java的对象参数传递是引用调用,实际上,Java的对象传递仍然是值调用。
引用调用:在参数传递的过程中,形参并不是实参的副本,而是实参本身。这种调用实参和形参在内存中实际上都是同样的一个区域,只是这个区域的表示(参数名)不同而已。
值调用:在参数传递过程中,创建了一个实参的副本——形参。形参和实参在内存中是两个完全不同的区域。因此形参内容的改变并不能影响到实参。
方法调用(call by) 是一个标准的计算机科学术语。方法调用根据参数传递的情况又分为值调用( call by reference ) 和引用调用( call by value ) 。江湖上有很多关于这两种调用的定义 ,最通常的说法是传递值的是值调用,传递地址的是引用调用。这其实很不恰当,这种 这些说法很容易让我们联想到Java的对象参数传递是引用调用,实际上,Java的对象参数传递仍然是值调用 。
以下摘自该段落:
http://hxraid.iteye.com/blog/428856
我们首先用一段代码来证实一下为什么Java的对象参数传递 是值调用。
Java代码
1. public class Employee {
2.
3. public String name=null;
4.
5. public Employee(String n){
6. this.name=n;
7. }
8. //将两个Employee对象交换
9. public static void swap(Employee e1,Employee e2){
10. Employee temp=e1;
11. e1=e2;
12. e2=temp;
13. System.out.println(e1.name+" "+e2.name); //打印结果:李四 张三
14. }
15. //主函数
16. public static void main(String[] args) {
17. Employee worker=new Employee("张三");
18. Employee manager=new Employee("李四");
19. swap(worker,manager);
20. System.out.println(worker.name+" "+manager.name); //打印结果仍然是: 张三 李四
21. }
22. }
上面的结果让人很失望,虽然形参对象e1,e2的内容交换了,但实参对象worker,manager并没有互换内容。这里面最重要的原因就在于形参e1,e2是实参worker,manager的地址拷贝。
大家都知道,在Java中对象变量名实际上代表的是对象在堆中的地址(专业术语叫做对象引用 )。在Java方法调用的时候,参数传递的是对象的引用。重要的是,形参和实参所占的内存地址并不一样,形参中的内容只是实参中存储的对象引用的一份拷贝。
如果大家对JVM内存管理中Java栈 的局部变量区 有所了解的话(可以参见《 Java 虚拟机体系结构 》),就很好理解上面这句话。在JVM运行上面的程序时,运行main方法和swap方法,会在Java栈中先后push两个叫做栈帧 的内存空间。main栈帧中有一块叫局部变量区的内存用来存储实参对象worker和manager的引用。而swap栈帧中的局部变量区则存储了形参对象e1和e2的引用。虽然e1和e2的引用值分别与worker和manager相同,但是它们占用了不同的内存空间。当e1和e2的引用发生交换时,下面的图很清晰的看出完全不会影响worker和manager的引用值。
Java对象参数传递虽然传递的是地址(引用),但仍然是值调用。是时候需要给引用调用和值调用一个准确的定义了。
值调用(call by value) : 在参数传递过程中,形参和实参占用了两个完全不同的内存空间。形参所存储的内容是实参存储内容的一份拷贝。实际上,Java对象的传递就符合这个定义,只不过形参和实参所储存的内容并不是常规意义上的变量值,而是变量的地址。咳,回过头想想:变量的地址不也是一种值吗!
引用调用(call by reference) : 在参数传递的过程中,形参和实参完全是同一块内存空间,两者不分彼此。 实际上,形参名和实参名只是编程中的不同符号,在程序运行过程中,内存中存储的空间才是最重要的。不同的变量名并不能说明占用的内存存储空间不同。
大体上说,两种调用的根本并不在于传递的是值还是地址(毕竟地址也是一个值),而是在于形参和实参是否占用同一块内存空间。事实上,C/C++的指针参数传递也是值调用,不信试试下面的C代码吧!
C代码
1. #include<stdio.h>
2. void swap(int *a1,int *b1){
3. int *t=a1;
4. a1=b1;
5. b1=t;
6. }
7. int main(){
8. int x1=100;
9. int x2=200;
10. int *a=&x1;
11. int *b=&x2;
12. printf("%d %d\n",*a,*b);
13. swap(a,b);
14. printf("%d %d\n",*a,*b);
15. return 0;
16. }
但C/C++是有引用调用的,这就是C/C++一种叫做引用的变量声明方法: int a; int &ra=a; 其中ra是a的别名,两者在内存中没有区别,占用了同一个内存空间。而通过引用(别名)的参数传递就符合引用调用的特点了。大家可以去试试
void swap(int &a1,int &b1);的运行结果。
转载于:https://www.cnblogs.com/wangzhewang/archive/2011/09/30/2196744.html
(重要)java都是值传递,与对象形参所指向的对象改变,其实参所指向的对象也相应改变并不矛盾(2011年9.30日一天写的两个程序的总结结果)...相关推荐
- java中形参不可以是对象吗_(重要)java都是值传递,与对象形参所指向的对象改变,其实参所指向的对象也相应改变并不矛盾(2011年9.30日一天写的两个程序的总结结果)...
1.0建立二叉树的代码,在java中必须创建二叉树的方法必须用返回值,因为不存在c语言中的引用传递,在java中只有值传递 代码1为正确,代码2(没有使用返回值)为错误.那么为什么之前的例子中将对象作 ...
- 为什么大家都说Java中只有值传递?
最近跟Java中的值传递和引用传递杠上了,一度怀疑人生.查了很多资料,加上自己的理解,终于搞清楚了,什么是值传递和引用传递.也搞明白了,为什么大家都说Java只有值传递,没有引用传递.原来,我一直以来 ...
- Stack Overflow上188万浏览量的提问:Java 到底是值传递还是引用传递?
来自:沉默王二 在逛 Stack Overflow 的时候,发现了一些访问量像阿尔卑斯山一样高的问题,比如说这个:Java 到底是值传递还是引用传递?访问量足足有 188万+,这不得了啊!说明有很多很 ...
- 为什么说 Java 中只有值传递?
对于初学者来说,要想把这个问题回答正确,是比较难的.在第二天整理答案的时候,我发现我竟然无法通过简单的语言把这个事情描述的很容易理解,遗憾的是,我也没有在网上找到哪篇文章可以把这个事情讲解的通俗易懂. ...
- 为什么说Java中只有值传递(另一种角度)
转载自 为什么说Java中只有值传递 对于初学者来说,要想把这个问题回答正确,是比较难的.在第二天整理答案的时候,我发现我竟然无法通过简单的语言把这个事情描述的很容易理解,遗憾的是,我也没有在网上找到 ...
- 一文彻底搞懂Java中的值传递和引用传递!
关于Java中方法间的参数传递到底是怎样的.为什么很多人说Java只有值传递等问题,一直困惑着很多人,甚至我在面试的时候问过很多有丰富经验的开发者,他们也很难解释的很清楚. 我很久也写过一篇文章,我当 ...
- 面试官:Java为什么只有值传递?
面试官爱问的一个基础问题:Java是值传递还是引用传递? 想必大家都对这个问题都有自己的看法,那到底事实是怎样的,我们又该如何回答面试官这个问题呢?今天咱们就来好好分析一波 值传递?引用传递? 首先, ...
- Java到底是不是值传递
最近在研究排序算法时遇到一个问题: int B[] = { 9, 8, 7, 6, 5, 4, 3, 2, 1 };// 从小到大希尔排序int n = B.length;ShellSort(B, n ...
- 为什么Java中只有值传递
原文链接:https://www.cnblogs.com/wchxj/p/8729503.html 在开始深入讲解之前,有必要纠正一下大家以前的那些错误看法了.如果你有以下想法,那么你有必要好好阅读本 ...
最新文章
- HDLBits 系列(33)Sequence Recognition with Mealy FSM
- node爬取app数据_node爬取拉勾网数据并导出为excel文件
- 按位异或运算和求反运算解析
- [转]2020年5月程序员工资统计,平均14542元
- 用WebORB实现flex + .net后台的Remoting
- 周鸿祎:比情怀更重要的硬件创业三定律
- Mac Backup软件:不要冒险您的数据!
- 数字调色盘【RGB和16位】
- 183.从不订购的客户
- android 微信 导出,微信好友怎么导出excel?微信导出原来这么简单
- 小程序 微信统计表格_用微信快速收集自定义报名统计,这款小程序做到了
- python读取excel画散点图对应多个y_Python数据分析:折线图和散点图的绘制
- java调用peopleSoft webservice
- 信号在PCB走线中的延迟
- 学大伟业:2019年生物竞赛学习方法
- 红帽Linux重置root密码
- 无法识别USB设备解决办法
- arp 已知mac找ip_怎么通过mac地址查ip 通过mac地址查ip方法【图文】
- 大规模量产上车!明星自驾公司鉴智机器人火热招聘中(算法/规控/软件/产品海量岗位来袭)...
- [JVM]成为JavaGC专家(1)—深入浅出Java垃圾回收机制
热门文章
- 编译、链接和运行详解
- 如何在网页中嵌入自己想要的字体(实例下载)
- Excel 技术篇-跨页签统计某一区域下符合条件值的数量方法,COUNTIF函数、数量统计公式的用法实例演示
- CTFshow 命令执行 web124
- 第七周实践项目2.3 顺序环形队列
- C++STL 常用 函数 用法
- 9.2 图像类型(灰度图像、彩色图像、二值图像以及图像间的转换)
- win7系统下配置openCV python环境附加 numpy +scipy安装
- 3.1.4 如何使深度学习模型达到人类水平以及超高人类水平
- 各个版本通道_绝地求生各个参数对画面的影响,软硬件优化帧数,拒绝做睁眼瞎...