有时候在想,java在调用方法时候究竟是按值传递还是按引用传递,之前有人说是基本数据类型按值传递,引用类型按引用传递。一时间,似乎都有道理。
笔者在此不追究字眼上的辨别识字能力,把自己对这个问题的理解阐述一下,笔者不想说这是按值传递还是按引用传递,自己理解就好了吧,毕竟java会用才是王道。
先看一下下面的代码:
package shb.java.testmemory;
public class TestMeo {
/**测试基本数据类型以及引用类型参数按值传递
* @Description:
* @author shaobn
* @param args
* @Date:2015-9-8 上午7:53:56
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
testInt();
testStr();
testPack();
testObj();
testObj_2();
}
//NO1.测试基本数据类型
public static void testInt(){
int num1 = 12;
System.out.println("Before change::"+num1);
changeInt(num1);
System.out.println("After change::"+num1);
}
//测试字符串类型
public static void testStr(){
String str = "helloworld";
System.out.println("Before change::"+str);
changeStr(str);
System.out.println("After change::"+str);
}
//测试包装类型
public static void testPack(){
Integer integer = new Integer(42);
System.out.println("Before change::"+integer);
changePack(integer);
System.out.println("After change::"+integer);
}
//测试引用类型
public static void testObj(){
Person person = new Person();
System.out.println("Before change::"+person.age);
changeObj(person);
System.out.println("After change::"+person.age);
}
//测试引用类型方式二
public static void testObj_2(){
Person person = new Person();
System.out.println("Before change::"+person.age);
changeObj_2(person);
System.out.println("After change::"+person.age);
}
public static void changeInt(int num){
num = 21;
}
public static void changeStr(String str){
str = "hellobeijing";
}
public static void changePack(Integer integer){
integer = new Integer(89);
}
public static void changeObj(Person person){
person.age = 87;
}
public static void changeObj_2(Person person){
person = new Person();
person.age = 78;
}
}
//引用类型测试类
class Person{
public int age = 78;
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
- 70.
- 71.
- 72.
- 73.
- 74.
- 75.
Look NO1:
说明一下:笔者在上面画的两张图着实不咋样,只能做到这种程度了。我们分析一下:当数据为基本数据类型时,我们传给形参的仅仅是一个实参的副本(Copy),当然由于栈内存变量共享的特征,这两个变量共同指向此变量值。
当我们对形参进行改变时,首先,在栈内存中会寻找是否存在新的变量值,如果有,则指向新的变量值(体现栈内存数据共享的特点)。如果没有的话,在栈内存中回开辟一块空间,存储新的变量值,同时形参变量会指向新的变量值。
此时我们发现,这时的变量值已经与实参的变量没有关系,两个独立的变量。所以经过函数后改变的变量值与之前的没有关系,故输出的还是之前的变量值。
另外,我们看到,当传递对象的引用时,person引用变量中存储的是Person对象在堆内存中的内存地址,所以传递的是内存地址(笔者理解为是一串数字)。此时两个形参变量是有共同的内存地址值,所以指向同一个内存对象。我们观察
发现,当我们改变对象中的属性值时,有牵一发而动全身的感觉,只要你改变这个对象,这个对象就被改变,而不存在另外开辟一个对象的概念(String类型和包装类型除外)。
PS:还没有写完,正在上班时间,晚上再写吧!
如有错误,请大家帮忙纠正一下。