【Java】带你了解Java的传值方式

【Java】带你了解Java的传值方式

一、结论

我先把结论放在前头,在java中,传递的对象如果是基础类型的话,就会直接将值传递过去(深拷贝),传递的对象是需要new的话,就是将对象的地址传递过去(浅拷贝)。 这个也困扰了我很久,c语言里还有指针可以区分,而java中就没有指针了,就很难区分了。

二、分析

1.直接上代码

package test;

/**

* @author xxj

* 检验java的传值方式

*/

public class TransmitValue {

private int a=0;

private MyClass m=new MyClass();

public static void main(String[] args){

TransmitValue tv=new TransmitValue();

tv.changeInt(tv.a);

tv.changeMyClass(tv.m);

System.out.println("tv.a:"+tv.a);

System.out.println("----");

System.out.println("tv.m:"+tv.m.i);

}

private void changeInt(int i){

i=10;

}

private void changeMyClass(MyClass m){

m.i=10;

}

public class MyClass{

int i=0;

}

}

运行的结果:

2.发生这种情况原因是什么呢?

最开始的总结中也提到了,需要new出来的对象才会,这是因为在new这个操作时,需要在jvm的堆中开辟一块空间,(jvm的组成以后有空再写,先埋个坑)开辟完成之后就返回这个对象的地址。 这时候,又有一个问题了,那不需要new的对象,放在哪里呢? 如果是方法内的对象是放在栈里面,如果是.class文件本身就带有的对象,则放在常量池中。 我从别的博客拉了一个图过来,大概是这样子,new出来的对象就是实例。 如果是存储在栈中,就不会存在引用,而是直接使用,换句话说,栈中的值,就是这个方法的本地变量。

3. 关于步骤1中代码的解释

看懂的话就直接跳过这一步了,没看懂的还有点疑惑的可以看一下。

为什么tv.a的值改变不了? 因为在调用changeInt方法时,tv.a中存储的数据就是值,不是地址,不存在引用,直接将数值传递过去肯定改变不了tv这个对象中的本地变量,改变的只是changeInt方法的本地变量。

为什么tv.m的值可以改变? 因为在调用changeMyClass方法时,tv.m中存储的数据是一个new出来的对象的地址,这个对象是存储在堆中的,所以在方法中,改变的是方法接收到的地址所找到的对象(也就是堆中的tv.m)的本地变量。

额外提一点

在changeMyClass方法中的MyClass m对象,是存储在这个方法的栈中的,一旦方法结束了,栈就会移除。

三、浅拷贝和深拷贝

浅拷贝 通过new创建出来的对象,一般在传值的时候都是浅拷贝,意思就是只复制了对象的地址,还是共用同一个对象。 一般出现在方法传参中,也不需要特地地去实现这个浅拷贝,算是默认的规则。

深拷贝 深拷贝是指能够生成两个一模一样的对象,这两个对象没有公用同一个地址,而是两个独立存在的对象。 一般的实现方法:可以通过转成JSON格式后,再调用new转成一个对象,这样就可以在堆中创建一个一模一样的对象了。

四、总结

说了那么多,其实就是传递的是地址还是值的问题。 引用C语言中的指针来做一个总结吧 在C中,是有指针和非指针的对象的,非指针的对象,就像java中的基础数据类型,只能传递值;指针的对象,就像java中new出来的对象,传递的是地址。而C语言需要我们主动的去创建一个对象时给这个对象设定是否是指针类型,也就是要不要加个*,但是在java中,java将这种需要主动设置的操作改为了默认的一种设定。

相关推荐

乐视电视怎么卸载软件(如何在乐视电视上卸载不需要的软件)
beat365下载唯一官方网

乐视电视怎么卸载软件(如何在乐视电视上卸载不需要的软件)

⌛ 10-13 👁️ 7188
精子在体外多久死亡
beat365在线体育正规吗

精子在体外多久死亡

⌛ 08-04 👁️ 7051