• Java——值传递和引用传递


    值传递

    在方法被调用时,实参通过形参把它的内容副本传入方法内部,此时形参接收到的内容是实参值的一个拷贝,因此在方法内对形参的任何操作,都仅仅是对这个副本的操作,不影响原始值的内容。

    先来看个例子:

    public static void valueCross(int age,float weight) {
    	System.out.println("传入的age值:"+age);
    	System.out.println("传入的weight值:"+weight);
    	age=23;
    	weight=60;
    	System.out.println("修改后的age值:"+age);
    	System.out.println("修改后的weight值:"+weight);
    }
    	
    	
    public static void main(String[] args) {
    	int age=10;
    	int weight=50;
    	valueCross(age,weight);
    	System.out.println("方法执行后的age:"+age);
    	System.out.println("方法执行后的weight:"+weight);
    		
    }
    

      

    运行结果:

    传入的age值:10
    传入的weight值:50.0
    修改后的age值:23
    修改后的weight值:60.0
    方法执行后的age:10
    方法执行后的weight:50
    

      

    我们可以看到valueCross方法执行后,实参age和weight的值并没有发生变化,这是什么原因?

    首先程序运行时,先从main方法开始执行,此时JVM为main()方法往虚拟机栈中压入一个栈帧,即为当前栈帧,用来存放main()中的局部变量表(包括参数)、操作栈、方法出口等信息,如a和w都是mian()方法中的局部变量,因此可以断定,age和weight是躺着mian方法所在的栈帧中

    接着调用valueCross方法,此时JVM为valueCross()方法往虚拟机中压入一个栈帧,即为当前栈帧,用于存放valueCross方法的局部变量等信息;因此age和weight是躺着valueCrossTest方法所在的栈帧中,而他们的值是从a和w的值copy了一份副本而得,如图:

    因此这两个age和weight对应的内容不是同一个,在valueCross方法中修改的只是自己栈中的内容,并没有修改main方法栈中的内容

    引用传递

    ”引用”也就是指向真实内容的地址值,在方法调用时,实参的地址通过方法调用被传递给相应的形参,在方法体内,形参和实参指向同一块内存地址,对形参的操作会影响的真实内容。

     先有一个Person类代码如下:

    public class Person {
    	
    	private String name;
    	private int age;
    	
    	public String getName() {
    		return name;
    	}
    	public void setName(String name) {
    		this.name = name;
    	}
    	public int getAge() {
    		return age;
    	}
    	public void setAge(int age) {
    		this.age = age;
    	}
    	
    
    }
    

      

     测试类代码:

    public class TestArr {
    	
    	
    	public static void PersonCross(Person person) {
    		 System.out.println("传入的person的name:"+person.getName());
    		 person.setName("敖丙");
    		 System.out.println("方法内重新赋值后的name:"+person.getName());
    	}
    	
    	public static void main(String[] args) {
    		Person p=new Person();
    		p.setName("哪吒");
    		p.setAge(4);
    		PersonCross(p);
    		System.out.println("方法执行后的name:"+p.getName());
    	}
    	
    }
    

      

    测试结果1:

    传入的person的name:哪吒
    方法内重新赋值后的name:敖丙
    方法执行后的name:敖丙
    

      

    我们可以看到PersonCross方法执行后,person的name值被改变了

    下面再看一段代码:

    public class TestArr {
    	public static void PersonCross(Person person) {
    		 System.out.println("传入的person的name:"+person.getName());
    		 person=new Person();//新添加的代码
    		 person.setName("敖丙");
    		 System.out.println("方法内重新赋值后的name:"+person.getName());
    	}
    	
    	public static void main(String[] args) {
    		Person p=new Person();
    		p.setName("哪吒");
    		p.setAge(4);
    		PersonCross(p);
    		System.out.println("方法执行后的name:"+p.getName());
    	}
    	
    }
    

      

    测试结果2:

    传入的person的name:哪吒
    方法内重新赋值后的name:敖丙
    方法执行后的name:哪吒
    

      

    有没有发现什么不同,这次PersonCross方法执行后person的name值并没有改变,这又是为什么?

    我们知道,java中的对象和数组是存放在堆内存中的,而堆内存是线程共享的,所以main方法执行时,会在堆内存中开辟一块内存,用来存储p对象的所有内容,然后再栈内存中创建一个引用p存储堆区中p对象的真实地址,如下图:

    当执行到PersonCross方法时,因为方法内有这么一行代码:person=new Person(),此时JVM在堆内存中又开辟了一块内存空间,假设地址为xo2222,那么现在的person则指向了xo2222这块内存,现在修改person的name值修改的是xo2222这块内存空间的值,不会改变xo3333的值,所以测试结果2中的name没有发生变化  

    引用传递本质上就是值传递,将引用变量的值传递给形参,因为引用变量的值存放的是地址值,所以当地址值传递给形参后,形参和实参指向同一块内存区域。 

  • 相关阅读:
    手机号中间几位用****代替
    正则小数点保留后两位;只允许汉字字母1-20位;10位数纯数字;正整数
    正则1-30之间的数值,支持1位小数
    给ul => li 中的最后一个li不加伪类after; 或者给最后一个和第一个不加伪类
    ajax请求, 前后端, 代码示例
    最简单的操作 jetty IDEA 【debug】热加载
    maven win 安装 与 IntelliJ IDEA 配置Maven【2018-11-14最新最有姿势攻略】
    mysql 在 win 安装 最全攻略(附转载的乱码终极解决方案)以及解决data too long for column 'name' at row 1, 一种可能就是因为编码一致性问题.
    SpringBoot无法书写主启动类的情况之一
    扯淡设计模式2:java,模板模式,
  • 原文地址:https://www.cnblogs.com/wugongzi/p/11297638.html
Copyright © 2020-2023  润新知