java值传递与引用传递

发布时间:2024年01月08日

没有繁琐的各种内存指向图片,而是从概念中进行解释

值传递场景

值传递包含String类型以及基本数据类型,仅仅传递值,
基本上只会有一种场景

   @Test
    public void testModify(){
   
        String str1 = "1";
        String str2 = this.modifyStr(str1);
        System.out.println("str1===>"+str1);  // str1===>1
        System.out.println("str2===>"+str2);  // str2===>2
    }

    
    private String modifyStr(String str){	// 形参str
        str = "2";		// 不管在这里进行什么操作,什么交换之类的,都不会改变实参(str1)
        return str;	
    }

此时吧值赋给str2了,str1的值没有变化,吧String类型换成其他的int类型等基本数据类型,都是有效的

引用传递场景

引用传递基本上会包含4种场景,其中最后2种主要探讨的是返回值,网络资料中较少提到
假设一个User类,仅有一个属性id,注入Getter,Setter方法

// 使用lombok自动写入getter,setter方法
@Data
public class User{
	private String id;
}

场景1

 	@Test
    public void testModify(){
        User user1 = new User();
        user1.setId("1");
         System.out.println("user1-->HashCode:"+user1.hashCode());	// user1-->HashCode:111
        this.modifyUser1(user1); 	
        System.out.println("user1.getId()===>"+user1.getId()); // user1.getId()===>2
        
    }

 private User modifyUser1(User user){  // 形参user
        user.setId("2");	// 引用了实参user1的地址,修改了实参user1的属性,所以user1也改了
        System.out.println("user-->HashCode:"+user.hashCode());	// user1-->HashCode:111
        return user;
    }

此时 modifyUser1() 方法里接收到的是user1的引用,因此改变形参user的值就等于改变user1的值。modifyUser1() 方法内user的hashCode和user1的hashCode一样,因此地址一样

场景2

    @Test
    public void testModify(){
        User user1 = new User();
        user1.setId("1");
        System.out.println("user1-->HashCode:"+user1.hashCode());	// user1-->HashCode:111
        this.modifyUser2(user1); 	
        System.out.println("user1.getId()===>"+user1.getId()); // user1.getId()===>1
        
    }

 private User modifyUser2(User user){ // 形参user
 		user = new User();  // 如果没有这行new User,则和场景1一样引用实参user1的地址
 							// 但是new User()了,地址指向发生了改变,因此此时user为一个新的对象
        user.setId("2");	
        System.out.println("user-->HashCode:"+user.hashCode());	// user1-->HashCode:222
        return user;
    }

此时 modifyUser2() 方法里一开始接收到的是user1的引用,但是后面new User()了,创建了个新的对象,引用改变了(user1的hashCode不等于user的hashCode了),指向的是new User,之后形参user的修改基于的都是对new User()的修改了

场景3
当引入返回值时,重新看看modifyUser1的方法

    @Test
    public void testModify(){
        User user1 = new User();
        user1.setId("1");
         System.out.println("user1-->HashCode:"+user1.hashCode());	// user1-->HashCode:111
        User user2 = this.modifyUser1(user1); 	
        System.out.println("user1.getId()===>"+user1.getId()); // user1.getId()===>2
        
        user2.setId("3");
        System.out.println("user2.getId()===>"+user2.getId()); // user2.getId()===>3
        System.out.println("user1.getId()===>"+user1.getId()); // user1.getId()===>3
    }

 private User modifyUser1(User user){  // 形参user
        user.setId("2");	// 引用了实参user1的地址,修改了实参user1的属性,所以user1也改了
        System.out.println("user-->HashCode:"+user.hashCode());	// user1-->HashCode:111
        return user;
    }

最后会发现user1和user2的id都为3,当把返回值赋给user2时,实际上返回的是引用,相当于user2 与user1的地址是一样的,所以此时修改user2的值,user1的值也会发生改变,实际上等价于以下代码

@Test
    public void testModify(){
    	User user1 = new User();
        user1.setId("1");
        User user2 = user1;			// 将user1的引用赋给user2,
        						// 此时修改user1等于改user2,修改user2等于改user1
        user2.setId("3");
        System.out.println(user1.getId());		// 3
        System.out.println(user2.getId());		// 3
    }

场景4
当引入返回值时,重新看看modifyUser2的方法

	@Test
    public void testModify(){

        User user1 = new User();
        user1.setId("1");
        System.out.println("user1-->HashCode:"+user1.hashCode());	// user1-->HashCode:111
        User user2 = this.modifyUser2(user1);
        System.out.println("user2-->HashCode:"+user2.hashCode());  // user2-->HashCode:222
        System.out.println("user1.getId():"+user1.getId());		// user1.getId():1
		System.out.println("user2.getId():"+user1.getId());		// user2.getId():2

    }
    
	private User modifyUser2(User user){  // 形参user
        user = new User();  // 如果没有这行new User,则和场景1一样引用实参user1的地址
        					// 但是new User()了,地址指向发生了改变,因此此时user为一个新的对象
        user.setId("2");
        System.out.println("user-->HashCode:"+user.hashCode()); // user-->HashCode:222
        return user;		// 将引用返回
    }

最后会发现user1的id仍然是1,user2的id则为2,这是因为在modifyUser2方法里new User()了,而这个new出来的user对象最后引用赋给了user2(两者hashCode都是一样的,都为222),而user1的hashCode仍为111,此时user1和user2地址不一样,任意修改user1也不会影响user2,实际上等价于以下代码

@Test
    public void testModify(){
    	User user1 = new User();
        user1.setId("1");
        User user2 = new User();		// 等价于在modifyUser2方法里new出来的对象
        user2.setId("2");
        // 此时user1和user2的引用就完全不一样了,修改互不影响
        System.out.println(user1.getId());		// 1
        System.out.println(user2.getId());		// 2
    }
文章来源:https://blog.csdn.net/cjy1575944940/article/details/135459130
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。