Java教程

java值传递详解

本文主要是介绍java值传递详解,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

公众号:jvm知识库

JAVA里面存在的是值传递还是引用传递,是不是对基本类型采取的是值引用,而对象(引用)类型采取的是引用传递?

首先需要先弄清楚什么是值传递,什么是引用传递???

值传递:将副本传递给方法,调用方法改变副本的值,但是并不改变原值
引用传递:传递的是对象的引用,对其修改,会改变原值。

Java中只存在值传递,不存在引用传递


Java中方法参数的使用情况:
一个方法不能够修改基本数据类型的参数。
原因在于基本数据类型参数,比如main方法中的参数,是存储在自身的栈帧中的,当调用方法时,会相应的建立新的栈帧,拷贝传入的参数,调用方法所做的修改也只是针对拷贝后的参数进行的,当离开这个函数,方法栈帧被销毁,被修改的参数也会被销毁。回到main栈帧中,原来的变量并没有被修改。

一个方法可以修改对象类型的参数。

原因在于传入对象类型作为参数时,传入的对象的地址,子方法根据地址找到对象对子方法内的引用进行赋值,方法内通过子方法对对象可以进行修改。方法结束时,栈桢被销毁,而main方法的引用的地址还是传入是的对象(对象并未销毁,但是可以在子方法被修改)。

 

具体流转过程请参考下面的代码及注释,来展示。

基本类型传参及内部处理的具体过程。

/**
 * 基本类型传参过程
 * 1.启动main函数,开辟内存栈空间。
 * 2.在main函数内存栈空间定义变量(引用)“i”
 * 3.在main函数内存栈空间对“i”进行赋值100
 *  3.1.从局部变量表查找是否有100,查找无100
 *  3.2.创建100并赋值给“i”,将100放入到局部变量表中。
 * 4.在main函数内存栈空间定义变量“u”
 * 5.在main函数内存栈空间对“u”进行赋值100
 *  5.1.从局部变量查找存在100
 *  5.2.将100赋值给u。此时“i”和“u”使用的局部变量表的同一个值100
 * 6.将i的值100(对象)递给方法transParam方法,值传递,不影响main函数中i的值。
 *
 * 7.创建新的内存栈空间。
 * 8.在add函数内存栈空间创建变量a
 * 9.在add函数内存栈空间将传入的值100赋值给a。
 *   注意:main方法的“i”和add方法的“a”是不同的变量(引用),占用不同的内存空间
    (即使i和a命名一致也不影响)
 * 10.在add函数内存栈空间定义变量(引用)“b”.
 * 11.在add函数内存栈空间对“b”进行赋值5
 *  11.1.在add函数内存栈空间局部变量表查找5,查找不存在5
 *  11.2.创建5并赋值给a,将5放入到局部变量表中。
 * 12.add函数打印出“add方法a的值为:5”
 * 13.add函数结束,对应的局部变量以及开辟的内存空间栈消失。
 * 14.回到main函数,打印出“main函数i的值为:100”
 */
public static void main(String[] args) {
    int i = 100;
    int u = 100;
    add(i);
    System.out.println("main函数i的值为:" + i);
}

public static void add(int a) {
    int b = 10;
    a = 5;
    System.out.println("add方法a的值为:" + a);
}

对象类型传参及内部处理的具体过程:

/**
 * 对象类型传参过程
 * 1.启动main函数,开辟内存栈空间。
 * 2.在main函数内存栈空间定义变量(引用)“user”
 * 3.在堆中创建新的User对象,假设对应的内存地址为“xxxxx1”
 * 3.在main函数内存栈空间对user赋值,指向的内存地址为“xxxxx1”
 * 4.在main函数对name和age进行赋值,会从局部变量表查找是否存在,
     参考(基本类型传参过程方法内赋值)
 * 5.打印出“main函数调用change方法前:张三的年龄是50”
 * 6.将“user”应用对应的内存地址“xxxxx1”传递给change方法,传递的是引用指向的地址。
 *
 * 7.创建新的内存栈空间。
 * 8.在change函数内存栈空间创建变量(引用)“u”
 * 9.对“u”进行赋值,从内存中找到地址为“xxxxx1”的对象,赋值给“u”。
 *   注意:main方法的“user”和change方法的“u”是不同的变量(引用),
     占用不同的内存空间(即使i和a命名一致也不影响)
 * 10.在change函数对地址为"xxxxx1"的对象的age属性重新赋值为51。
 * 13.change函数结束,但是地址为"xxxxx1"的张三的年龄老了一岁,但仍然还是张三那个人。
 * 14.回到main函数,打印出“main函数调用change方法后:张三的年龄是51”
 */
public static void main(String[] args) {
    User user = new User();
    user.name = "张三";
    user.age = 50;
    System.out.println("main函数调用change方法前:" + 
        user.name + "的年龄是" + user.age);
    change(user);
    System.out.println("main函数调用change方法后:" + 
        user.name + "的年龄是" + user.age);
}

public static void change(User u) {
    u.age = 51;
}

更底层的过程就留给jvm工程师吧,知道的太多了也不好(主要是菜)。

这篇关于java值传递详解的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!