博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java是传值还是传引用
阅读量:4991 次
发布时间:2019-06-12

本文共 4274 字,大约阅读时间需要 14 分钟。

1,C/C++中的指针、引用、句柄

C++primer中对 对象的定义:对象是指一块能存储数据并具有某种类型的内存空间,一个对象a,它有值和地址&a。

指针:p也是对象,它同样有地址&p和存储的值p,只不过,p存储的数据类型是数据的内存地址。

对象有常量(const)和变量之分,既然指针本身是对象,那么指针所存储的地址也有常量和变量之分,常量指针是指,指针这个对象所存储的地址是不可以改变的,而指向常量的指针的意思是,不能通过该指针来改变这个指针所指向的对象。

引用:引用是对象的别名,可以看作是一个常量指针,相比于普通指针功能受限但是安全性更高(引用的一个优点是它一定不为空)。定义一个引用的时候,程序把该引用和它的初始值绑定在一起,而不是拷贝它。计算机必须在声明r的同时就要对它初始化,并且,r一经声明,就不可以再和其它对象绑定在一起了。

句柄:是指针的指针,句柄实际上是一个数据,是一个Long (整长型)的数据。句柄是一个标识符,是拿来标识对象或者项目的,它就象我们的姓名一样。

Windows是一个以虚拟内存为基础的操作系统。在这种系统环境下,Windows内存管理器经常在内存中来回移动对象,依此来满足各种应用程序的内存需要。对象被移动意味着它的地址变化了。如果地址总是如此变化,我们该到哪里去找该对象呢?为了解决这个问题,Windows操作系统为各应用程序腾出一些内存储地址,用来专门登记各应用对象在内存中的地址变化,而这个地址(存储单元的位置)本身是不变的。Windows内存管理器在移动对象在内存中的位置后,把对象新的地址告知这个句柄地址来保存。

2,java中的引用和句柄

 

1)java中的3种数据类型:

基本数据类型(数值型(整数类型(int,short,byte,long),浮点类型(float,double)),字符型(char),布尔型(boolean));

引用数据类型(类(class),接口(interface),数组([])));

null类型;

2)java中的引用和句柄

句柄:为了区别引用类型的变量标识符和基本数据类型变量标识符,我们特别的(特意的)使用Handle来称呼引用类型的变量标识符。

句柄其实就是变量,不同于基本变量的关键,它是一种间接寻址方式。

引用:对象的引用是创建对象时的返回值(引用是new表达式的返回值)。

例:new A(); 这里真正创建了一个对象,但我们没有用句柄去持有(hold、拿着、保存)该引用。handle是变量,reference是一种变量值。

(1)句柄 a——常见为A a;

(2)创建对象——new A();这才是真正的创建对象。对象一般通过new表达式来创建。计算new表达式的值的整个过程,在微观上完成了对象的创建和这个对象自己的成员变量的初始化,在宏观上得到new表达式的值,这个值称为新对象的引用;

(3)引用:new A()的值。引用可以简单的看作对象占据内存空间的地址;通过对象的引用,就可以方便的与其他对象区别开来,引用就是对象独特的身份标识。

(4)句柄的初始化:句柄 = 引用;即把引用赋值给句柄,如语句a=new A();完成句柄的初始化后,就可以用句柄遥控对象了

参考:

http://www.cnblogs.com/lsjwzh/archive/2010/05/08/1730480.html

3,传值和传引用问题的由来

C 语言中将一个数据作为参数传递给某个函数的时候,就有两种方式:传值,或是传指针,它们的区别,可以用一个简单的例子说明:

1 void SwapValue(int a, int b) { 2     int t = a; 3     a = b; 4     b = t; 5 } 6 void SwapPointer(int * a, int * b) { 7     int t = * a; 8     * a = * b; 9     * b = t;10 }11 void main() {12     int a = 0, b = 1;13     printf("1 : a = %d, b = %d\n", a, b);14     SwapValue(a, b);15     printf("2 : a = %d, b = %d\n", a, b);16     SwapPointer(&a, &b);17     printf("3 : a = %d, b = %d\n", a, b);18 }

运行结果:

1 : a = 0, b = 1
2 : a = 0, b = 1
3 : a = 1, b = 0

大家可以明显的看到,按指针传递参数可以方便的修改通过参数传递进来的值,而按值传递就不行。

在java中:

使用类似 SwapValue 的方法仍然不能改变通过参数传递进来的简单数据类型的值,但是如果是一个对象,则可能将其成员随意更改。

这很像是 C 语言中传值/传指针的问题。但是 Java 中没有指针,于是很多人就把这个问题演变成了传值/传引用的问题。

4,java中 的参数传递

1 public class Test { 2     public static void test(boolean test, int a, int[] b, String c,StringBuffer d) { 3         test = ! test; 4         a = 10; 5         int temp = b[0]; 6         b[0] = b[1]; 7         b[1] = temp; 8         c = "cc"; 9         d.append(" word");10         System.out.println("In test(boolean) : test = " + test);11         System.out.println("In a(int) : a = " + a);12         System.out.println("In b(int[]) : b = " + b[0] + b[1]);13         System.out.println("In c(String) : c = " + c);14         System.out.println("In d(StringBuffer) : d = " + d);15         System.out.println();        16     }17     public static void main(String[] args) {18         boolean test = true;19         int a = 1;20         int[] b = {6,7};21         String c = new String("c");22         StringBuffer d = new StringBuffer("hello");23         System.out.println("Before test(boolean) : test = " + test);24         System.out.println("Before a(int) : a = " + a);25         System.out.println("Before b(int[]) : b = " + b[0] + b[1]);26         System.out.println("Before c(String) : c = " + c);27         System.out.println("Before d(StringBuffer) : d = " + d);28         System.out.println();        29         test(test,a,b,c,d);30         System.out.println("After test(boolean) : test = " + test);31         System.out.println("After a(int) : a = " + a);32         System.out.println("After b(int[]) : b = " + b[0] + b[1]);33         System.out.println("After c(String) : c = " + c);34         System.out.println("After d(StringBuffer) : d = " + d);35     }36 }

查阅了网上有好多关于这个问题的争论,我觉得主要是对对象,引用,句柄这些概念的理解有所不同造成的。

基于上述概念和实验结果,我们的结论是:

1)对于基本数据类型的参数传递是按值传递的,即传入方法中的是基本数据类型的一个副本

例如实验中的boolean类型的test和int类型的a,传入方法改变其值,源值没有改变。

2)对于引用数据类型的参数是按引用(对象的存储地址值)传递的,即传入方法的不是引用数据类型的实例(对象)的一个副本。

那为什么上述实验中String类型c并没有改变源对象呢?

我们仔细看一下,第一步把“c”对象的引用传给方法里的句柄c(这里的句柄(变量)c是方法里的与main()函数里的句柄c没有关系);

        第二步在方法里又把“cc”对象的引用赋给了方法里的句柄c。(关键是这里的赋值操作使方法里的句柄c与main()函数里的对象没有了任何关系)

        所以,方法里的句柄c里存的引用是“cc”对象的地址,而main()函数里句柄c里存的引用是“c”对象的地址。

参考:

http://old.bccn.net/Article/kfyy/java/jszl/200601/3069.html

 

转载于:https://www.cnblogs.com/xdyixia/p/9130702.html

你可能感兴趣的文章
uva 1557 - Calendar Game(博弈)
查看>>
HDU1051 Wooden Sticks 【贪婪】
查看>>
十大经典数据挖掘算法
查看>>
Rhythmbox乱码的解决的方法
查看>>
中纪委:抗震中官员临危退缩玩忽职守将被严处
查看>>
MySQL 8.0.12 基于Windows 安装教程
查看>>
在hue中使用hive
查看>>
eclipse快捷键
查看>>
在指定文本里记录内容
查看>>
Android WebView常见问题及解决方案汇总
查看>>
[BZOJ4025]二分图
查看>>
HTML5 Canvas玩转酷炫大波浪进度图
查看>>
创建ASP.NET Core MVC应用程序(5)-添加查询功能 & 新字段
查看>>
电话录音系统说明书
查看>>
JVM(1)——IDEA启动分配内存大小及GC日志打印
查看>>
oracle 批量更新之update case when then
查看>>
text3
查看>>
自己写的连击文字特效
查看>>
【Android】eclipse打不开的解决办法和“Jar mismatch! Fix your dependencies”的解决
查看>>
Mysql查询某字段值重复的数据
查看>>