您的位置:首页 > 编程语言 > Java开发

Java中参数传递是值传递,还是引用传递的一次深究

2011-11-06 12:02 691 查看
Java中参数传递是值传递,还是引用传递的一次深究

是我自己分析的,可能不准确,请大牛们指导,欢迎大家拍砖

1 先回顾一下java基础内容:对象在内存分配方式

public static void main(String[] args)
{
Person p = new Person();
}


这一句"Person p = new Person();" 分配了两个对象.

一个是引用对象p分配在栈中,

一个是实体对象new Person(),分配在堆上

并且p保存了实体对象的地址

如下图所示

栈内存 堆内存



引用对象p指向了 一个实体对象 Person.

对于堆上和栈上分配内存的释放,有java基础的人都知道,在这里就不说了。不知道可以百度。

2 函数中参数传递的两种类型

2.1 参数类型为基本类型 如 int float 等等

基本类型传递举例

public class PersonDemo
{
public static void main(String[] args)
{
int n =100;
System.out.println(n);
changeN(n);
System.out.println(n);
}

public static int changeN(int a)
{
return a = a+1;
}
}


相信大家都知道结果:

100

100

从这里,我们都可以看出java中方法的参数传递是按值传递的。

2.2 参数类型为对象类型 如Person

例子一

public class PersonDemo
{
public static void main(String[] args)
{
Person p = new Person();
p.age = 10;
System.out.println("传递前age=" +p.age);
changeAge(p);
System.out.println("传递后age=" +p.age);
}
public static int changeN(int a)
{
return a = a+1;
}
public static void changeAge(Person per)
{
per.age += 10;
}
}

class Person
{
int age;
}


输出结果:

传递前age=10

传递后age=20

可能有人会想 例子一这里传递的是对象的引用。

例子二

public class PersonDemo
{
public static void main(String[] args)
{
Person p = new Person();
p.age = 10;
System.out.println("传递前age=" +p.age);
changePerson(p);
System.out.println("传递后age=" +p.age);
}
public static int changeN(int a)
{
return a = a+1;
}
public static void changeAge(Person per)
{
per.age += 10;
}
public static void changePerson(Person per)
{
Person p1 = new Person();
p1.age = 50;
per =p1;
}
}
class Person
{
int age;
}


输出结果

传递前age=10

传递后age=10

可能有人会想 例子二中这里传递的是对象的引用的一个复制。

对于例子二我想了一个图示



对于第二种参数传入类型为对象的情况,解释有3种

说法1 参数是按引用传递的,对于说法1 还有两种解释,

解释1 引用传递时是传入对象的引用

解释2 引用传递时是传入对象引用的复制

说法2 参数是按值传递

到底关于对象类型的参数,java中是按什么传递的,

其实java中不管是对象参数还是基本类型参数,都是按值传递的。

我们可以对方法中参数某些值进行打印 比如 Hashcode

这是部分代码 Person类可以参考上面定义的。

public class PersonDemo
{

public static void main(String[] args)
{
Person p = new Person();
System.out.println("传递前hascode=" +p.hashCode());
hc(p);
}

public static void hc(Person per)
{
System.out.println("传递后hascode=" +per.hashCode());
}
}


输出结果

传递前hascode=29855319

传递后hascode=29855319

我们可以看出 参数中传递进来的对象的hashcode和参数外面的一样。

我们再看一个例子

public class PersonDemo
{
static Person CP = new Person();
public static void main(String[] args)
{
equalPer(CP);
}

public static void equalPer(Person per)
{
System.out.println("比较对象结果:" +(per == CP));
}
}


输出结果

比较对象结果:true

用==进行比较, 我们一直都认为是比较的值相等,而不是内容。

查看JDK文档中队 hashcode方法的描述,有这么一段话

实际上,由 Object 类定义的 hashCode 方法确实会针对不同的对象返回不同的整数。

这一般是通过将该对象的内部地址转换成一个整数来实现的,但是 JavaTM 编程语言不需要这种实现技巧。)

通过上面的分析,关于对象传递,传递的是对象的一个引用(这里的引用跟c++中的引用不是一回事),这里的引用对象

是"该对象的内部地址转换成一个整数" ,其实就是一个整数。

所以我们可以肯定了java中不管是对象参数还是基本类型参数,都是按值传递的。

附带说明:

c++里面关于对象的一些知识

c++也是面向对象的语言,c++里面建立对象的方法是 :Person * p1 = new Person;

new出来返回的是一个对象的指针,java中没有指针这个说法。

而这个栈上的指针p也是指向堆上的new Person对象。

貌似跟java很类似,的确很类似 如果你在c++中也实现类似的改变Person中age的方法

public  void changeAge(Person * p)
{
p->age += 10;
}

他也改变 Person中age的值。他传入的是一个指针类型,从这个角度可以看出,C++中传递是按值传递的。

C++中按引用传递的方式是这样的

public  void changeAge(Person & p)
{
p.age += 10;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: