JAVA传值和传引用的区别

1.基本概念

1.1 传值

传递的是值的副本。方法中对副本的修改,不会影响到调用方,也就是不会影响原来的值;

1.2 引用

传递的是引用的副本,共用一个内存,会影响到调用方。此时,形参和实参指向同一个内存地址。

但是对引用副本本身(对象地址)的修改,如设置为null,重新指向其他对象不会影响到调用方

2.验证

2.1 基本数据类型

    /**
     * 基本数据类型
     */
    @Test
    public void test2(){
        int value = 1;
        log.info("当前值:{}",value);
        change(value);
        log.info("最终值:{}",value);
    }
​
    private void change(int value) {
        value = 100*value;
    }

执行结果

当前值:1
最终值:1

总结

从输出的的结果中可以看到原本的value并没有被修改,即传值传递的是值的副本,不会影响到本身。

2.2 引用数据类型

对象

package com.kang.webservice.pojo;
​
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
​
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
​
    private Integer id;
    private String userId;
    private String userName;
   
}
  
 /**
     * 引用数据类型
     */
    @Test
    public void test3(){
        log.info("=========================对象================================");
        User user = new User(4, "tom", "汤姆");
        log.info("当前值:{}",user);
        changeObject(user);
        log.info("最终值:{}",user);
        log.info("=========================数组================================");
        List list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        log.info("当前值:{}",JSON.toJSONString(list));
        changeList(list);
        log.info("最终值:{}",JSON.toJSONString(list));
        log.info("=========================Map================================");
        Map map = new HashMap<>();
        map.put("user",new User(2,"66","测试01"));
        log.info("当前值:{}",JSON.toJSONString(map));
        changeMap(map);
        log.info("最终值:{}",JSON.toJSONString(map));
    }
​
    private void changeMap(Map map) {
        User user = map.get("user");
        user.setUserId("没有赎金惨遭撕票");
    }
​
    private void changeList(List list) {
        list.remove(1);
        list.add(5);
    }
​
    private void changeObject(User user) {
        user.setUserId("我被不发份子绑票了");
    }

执行结果

14:44:41.149 [main] INFO com.kang.webservice.DemoTest - =========================对象================================
14:44:41.151 [main] INFO com.kang.webservice.DemoTest - 当前值:User(id=4, userId=tom, userName=汤姆)
14:44:41.159 [main] INFO com.kang.webservice.DemoTest - 最终值:User(id=4, userId=我被不发份子绑票了, userName=汤姆)
14:44:41.159 [main] INFO com.kang.webservice.DemoTest - =========================数组================================
14:44:41.208 [main] INFO com.kang.webservice.DemoTest - 当前值:[1,2,3,4]
14:44:41.209 [main] INFO com.kang.webservice.DemoTest - 最终值:[1,3,4,5]
14:44:41.209 [main] INFO com.kang.webservice.DemoTest - =========================Map================================
14:44:41.244 [main] INFO com.kang.webservice.DemoTest - 当前值:{"user":{"id":2,"userId":"66","userName":"测试01"}}
14:44:41.244 [main] INFO com.kang.webservice.DemoTest - 最终值:{"user":{"id":2,"userId":"没有赎金惨遭撕票","userName":"测试01"}}

总结

可以看到方法中的引用数据类型的值被修改了,因为传引用后指向的是同一个地址,修改的实际上也就是这个地址上的值,另外要注意一点的是如果对象被重新创建或赋值为null,即new会重新指向其他对象,不影响其原对象的值。

2.3 传final修饰的String,Integer等类型

public final class String
    implements java.io.Serializable, Comparable, CharSequence,
               Constable, ConstantDesc {
public final class Integer extends Number
        implements Comparable, Constable, ConstantDesc {

 

/**
     * String,Integer,Long
     */
    @Test
    public void test4(){
        log.info("=========================String================================");
        String value = "我是真的美猴王";
        log.info("当前值:{}",value);
        changeString(value);
        log.info("最终值:{}",value);
        log.info("=========================Integer================================");
        Integer i = 10;
        log.info("当前值:{}",i);
        changeInteger(i);
        log.info("最终值:{}",i);
    }
​
    private void changeInteger(Integer i) {
        i = 10000*i;
    }
​
    private void changeString(String value) {
        value = "你看我几分像从前";
    }

结果

14:55:08.815 [main] INFO com.kang.webservice.DemoTest - =========================String================================
14:55:08.817 [main] INFO com.kang.webservice.DemoTest - 当前值:我是真的美猴王
14:55:08.818 [main] INFO com.kang.webservice.DemoTest - 最终值:我是真的美猴王
14:55:08.819 [main] INFO com.kang.webservice.DemoTest - =========================Integer================================
14:55:08.819 [main] INFO com.kang.webservice.DemoTest - 当前值:10
14:55:08.819 [main] INFO com.kang.webservice.DemoTest - 最终值:10

总结

String、Integer、Double等immutable类型因为类的变量设为final属性,无法被修改,只能重新赋值或生成对象。当Integer作为方法参数传递时,对其赋值会导致原有的引用被指向了方法内的栈地址,失去原有的的地址指向,所以对赋值后的Integer做任何操作都不会影响原有值。

3.总结

  • 基本类型(byte,short,int,long,double,float,char,boolean)为传值,传的是副本所以不会影响原有的值

  • 对象类型(Object,数组,容器)为传引用,会影响原来的值

  • String、Integer、Double等immutable类型因为类的变量设为final属性,无法被修改,只能重新赋值或生成对象。当Integer作为方法参数传递时,对其赋值会导致原有的引用被指向了方法内的栈地址,失去原有的的地址指向,所以对赋值后的Integer做任何操作都不会影响原有值。

你可能感兴趣的:(JAVA知识回顾,java,jvm,servlet)