Java参数传递小结
2017-09-06 15:14
176 查看
根据代码,判断哪段代码可以使打印出来的1跟2的顺序相反
运行以下代码就可以知道答案啦
要了解参数传递,那么我们首先要了解一下基本类型和引用类型的变量有什么区别。基本类型的变量中存储的是一个基本类型的值;而引用类型的变量中,存储的是一个指向内存某处空间的地址,也就是引用类型的变量指向了内存中某处。当我们用“=”操作基本类型变量的时候, 就是直接改变了变量的值如 int a = 0; a = 33;当我们用“=”操作引用类型变量的时候, 改变的是引用变量中所存的地址,也就是改变了它的指向,如String a ="aaaa"; a = "bbbb"; a一开始指向了常量池里的aaaa字符串,后来又指向了常量池里的bbbb字符串。
而参数传递就是一个赋值的过程,不管这个值是一个基本类型,还是一个地址,都是赋值。
这两道题最主要的还是要认清上面所说的参数传递的一个本质。在方法的参数列表中,标识符只不过是一个代号而已,千万不要给这些标识符骗了。比方说,这die段代码中的
private static void function(Demo d1,Demo d2){
Demo temp;
temp=d1;
d1=d2;
d2=temp;
}
d1,d2完全可以用a b来替代
private static void function(Demo a,Demo b){
Demo temp;
temp = a;
a = b;
b = temp;
}
也就是说,在调用function(d1,d2);这个方法的时候,a = d1,b = d2;因为d1是一个变量名,是一个引用变量,因此它里面存放的是Demo的一个名为d1的对象地址而已吧(比如@0x0002),那么这个时候呢,d1里面的值就赋给了a,a也就同样指向了Demo的对象d1的地址;b则指向了对象d2的地址。这在两段代码中都是一样的。
然后在第二段代码中,temp随后也指向了d1(temp = a),而a随后指向了d2(a = b), b随后指向了d1(b = temp)。在这个过程中只是局部变量a b 指向的内存地址改变了,并没有改变d1 d2这两个引用变量的值。所以d1还是指向Demo的一个对象d1所在的内存地址(@0x0002),d2还是指向Demo的一个对象d1所在的内存地址d2。
再回头看第一段代码中的function方法
private static void function(Demo ff,Demo ee){
int a;
a = ff.a;
ff.a = ee.a;
ee.a = a;
}
因为方法体中已经有了局部变量a,所以这里我就在参数列表中将d1,d2用ff和ee替换。那么,这个时候假设d1指向了内存地址@0x1111 d2指向内存地址@0x2222,那么调用了function方法之后,ff也指向了@0x1111,ee指向了@0x2222, 然后a = ff.a则是对@0x1111这个地址存放的Demo的对象d1中的成员变量a的值赋值给了a这个变量,也就是a现在的值为1,随后ff.a = ee.a则是将Demo的另一个对象d2中的成员变量a的值赋值给了ff.a,那么ff.a的值就变成了2,ee.a
= a 则是把1赋值给了ee.a,这两个操作改变了Demo两个对象的成员变量a在内存中的值,所以后面打印的时候,看到的结果是原来d1.a d2.a的值1跟2分别变成了 2跟1。
一般网上讨论的Java参数传递是值传递还是引用传递问题,我觉得可以用Yolanda在知乎上的回答来理解。一直以来大家对于值传递,引用传递都只是有一个模糊的概念而已,所以才会有这种讨论。值传递和引用传递,属于函数调用时参数的求值策略(Evaluation
Strategy),这是对调用函数时,求值和传值的方式的描述,而非传递的内容的类型(内容指:是值类型还是引用类型,是值还是指针)。也就是说,假设我用某一门参数传递是值传递的语言,我在调用方法的时候,不管给参数传递的是具体的一个整型变量,还是只是一个对象的引用,这都无法改变我是使用值传递的这个事实。值传递的传值方式是原值的副本,所以函数中无法改变原始的对象;引用传递不会创建副本,它的传值方式是原值,因此函数可以改变原始对象。而Java是Pass
by value
有些同学可能会疑惑,能够改变对象中的成员变量的值,为什么说Java是值传递呢?这里需要明确的是,我们并没有改变原始对象,也就是我们并没有改变传进来的d1 d2这两个引用变量的值,我们只是在方法中创建了两个新的变量ff ee,指向了d1 d2所指向的内存地址,然后通过这个内存地址修改了对象中的值。
这里还有几道题可以练习一下
http://www.xuebuyuan.com/897461.html http://blog.darkmi.com/2010/11/28/1430.html
然后呢,这里有一个比较特殊的地方,就是String类。
a在内存中,指向了常量池里面的aaaa字符串,但是我们在直接打印a的时候打印的结果却不像其他对象的引用变量一样,可以打印指向对象的地址,而是直接打印出String类型在常量池里面的值,所以String看起来很像是基本类型。要详细了解String类,可以参考一下这篇文章。String是值类型,还是引用类型
String类是纯粹的对象,特殊的地方在于有
字符串直接量 和 字符串常量池 和 字符串拼接的运算符重载。而且与基本类型无关,之所以看起来像是基本类型,主要是因为String类是不可变类(构造后不可改变,没有提供可改变自身状态的方法)。
class Demo{ int a; public Demo(int a){ this.a=a; } } public class TestQuote{ public static void main(String args[]){ Demo d1=new Demo(1); Demo d2=new Demo(2); System.out.println(d1.a); System.out.println(d2.a); function(d1,d2); System.out.println(d1.a); System.out.println(d2.a); } private static void function(Demo d1,Demo d2){ int a; a=d1.a; d1.a=d2.a; d2.a=a; } }
class Demo{ int a; public Demo(int a){ this.a=a; } } public class TestQuote{ public static void main(String args[]){ Demo d1=new Demo(1); Demo d2=new Demo(2); System.out.println(d1.a); System.out.println(d2.a); function(d1,d2); System.out.println(d1.a); System.out.println(d2.a); } private static void function(Demo d1,Demo d2){ Demo temp; temp=d1; d1=d2; d2=temp; } }
运行以下代码就可以知道答案啦
要了解参数传递,那么我们首先要了解一下基本类型和引用类型的变量有什么区别。基本类型的变量中存储的是一个基本类型的值;而引用类型的变量中,存储的是一个指向内存某处空间的地址,也就是引用类型的变量指向了内存中某处。当我们用“=”操作基本类型变量的时候, 就是直接改变了变量的值如 int a = 0; a = 33;当我们用“=”操作引用类型变量的时候, 改变的是引用变量中所存的地址,也就是改变了它的指向,如String a ="aaaa"; a = "bbbb"; a一开始指向了常量池里的aaaa字符串,后来又指向了常量池里的bbbb字符串。
而参数传递就是一个赋值的过程,不管这个值是一个基本类型,还是一个地址,都是赋值。
这两道题最主要的还是要认清上面所说的参数传递的一个本质。在方法的参数列表中,标识符只不过是一个代号而已,千万不要给这些标识符骗了。比方说,这die段代码中的
private static void function(Demo d1,Demo d2){
Demo temp;
temp=d1;
d1=d2;
d2=temp;
}
d1,d2完全可以用a b来替代
private static void function(Demo a,Demo b){
Demo temp;
temp = a;
a = b;
b = temp;
}
也就是说,在调用function(d1,d2);这个方法的时候,a = d1,b = d2;因为d1是一个变量名,是一个引用变量,因此它里面存放的是Demo的一个名为d1的对象地址而已吧(比如@0x0002),那么这个时候呢,d1里面的值就赋给了a,a也就同样指向了Demo的对象d1的地址;b则指向了对象d2的地址。这在两段代码中都是一样的。
然后在第二段代码中,temp随后也指向了d1(temp = a),而a随后指向了d2(a = b), b随后指向了d1(b = temp)。在这个过程中只是局部变量a b 指向的内存地址改变了,并没有改变d1 d2这两个引用变量的值。所以d1还是指向Demo的一个对象d1所在的内存地址(@0x0002),d2还是指向Demo的一个对象d1所在的内存地址d2。
再回头看第一段代码中的function方法
private static void function(Demo ff,Demo ee){
int a;
a = ff.a;
ff.a = ee.a;
ee.a = a;
}
因为方法体中已经有了局部变量a,所以这里我就在参数列表中将d1,d2用ff和ee替换。那么,这个时候假设d1指向了内存地址@0x1111 d2指向内存地址@0x2222,那么调用了function方法之后,ff也指向了@0x1111,ee指向了@0x2222, 然后a = ff.a则是对@0x1111这个地址存放的Demo的对象d1中的成员变量a的值赋值给了a这个变量,也就是a现在的值为1,随后ff.a = ee.a则是将Demo的另一个对象d2中的成员变量a的值赋值给了ff.a,那么ff.a的值就变成了2,ee.a
= a 则是把1赋值给了ee.a,这两个操作改变了Demo两个对象的成员变量a在内存中的值,所以后面打印的时候,看到的结果是原来d1.a d2.a的值1跟2分别变成了 2跟1。
一般网上讨论的Java参数传递是值传递还是引用传递问题,我觉得可以用Yolanda在知乎上的回答来理解。一直以来大家对于值传递,引用传递都只是有一个模糊的概念而已,所以才会有这种讨论。值传递和引用传递,属于函数调用时参数的求值策略(Evaluation
Strategy),这是对调用函数时,求值和传值的方式的描述,而非传递的内容的类型(内容指:是值类型还是引用类型,是值还是指针)。也就是说,假设我用某一门参数传递是值传递的语言,我在调用方法的时候,不管给参数传递的是具体的一个整型变量,还是只是一个对象的引用,这都无法改变我是使用值传递的这个事实。值传递的传值方式是原值的副本,所以函数中无法改变原始的对象;引用传递不会创建副本,它的传值方式是原值,因此函数可以改变原始对象。而Java是Pass
by value
有些同学可能会疑惑,能够改变对象中的成员变量的值,为什么说Java是值传递呢?这里需要明确的是,我们并没有改变原始对象,也就是我们并没有改变传进来的d1 d2这两个引用变量的值,我们只是在方法中创建了两个新的变量ff ee,指向了d1 d2所指向的内存地址,然后通过这个内存地址修改了对象中的值。
这里还有几道题可以练习一下
http://www.xuebuyuan.com/897461.html http://blog.darkmi.com/2010/11/28/1430.html
然后呢,这里有一个比较特殊的地方,就是String类。
public class Test { public static void change(String s) { s = "bbbb"; } public static void main(String[] args) { String a = new String("aaaa"); //String a = "aaaa";也可以达到一样的效果 System.out.println(a); //结果为aaaa change(a); System.out.println(a); //结果为aaaa } }
a在内存中,指向了常量池里面的aaaa字符串,但是我们在直接打印a的时候打印的结果却不像其他对象的引用变量一样,可以打印指向对象的地址,而是直接打印出String类型在常量池里面的值,所以String看起来很像是基本类型。要详细了解String类,可以参考一下这篇文章。String是值类型,还是引用类型
String类是纯粹的对象,特殊的地方在于有
字符串直接量 和 字符串常量池 和 字符串拼接的运算符重载。而且与基本类型无关,之所以看起来像是基本类型,主要是因为String类是不可变类(构造后不可改变,没有提供可改变自身状态的方法)。
相关文章推荐
- Groovy小结:java调用Groovy方法并传递参数
- JAVA前端与后端参数传递方法小结
- Java Web中前台与后台传递参数小结
- JAVA中函数调用参数传递的理解(值传递和引用传递的理解)
- java向线程中传递参数的方法
- java把函数作为参数传递
- java 参数传递是引用传递还是值传递?
- java程序用post方式给某一网页传递参数
- Java函数参数是值传递的
- Java学习(八)方法参数传递方式
- java调用kettle向job(任务)和transformation(转换)传递参数实例
- java参数传递时到底是值传递还是引用传递
- java中方法的参数传递机制
- Tomcat等应用启动脚本中的-D参数 [java的系统参数传递]
- java调用linux命令 传递多个参数和通配符的问题
- JAVA HttpURLConnection Post方式提交传递参数
- java服务器端接收json格式传递的参数
- java 用get方式传递参数乱码问题解决
- Delphi利用jni向java程序中传递参数
- Jni中C++和Java的参数传递