为什么说java只有值传递

java中的值传递

我们都知道,在java中,简单的swap交换两个对象是行不通的,对于基本数据类型这很好理解,因为方法上的参数是值的复制,就是很好理解的那种值传递。但是如果是交换两个对象该如何理解呢?

@Data
public class Number {

    private Integer num;

    public Number(Integer n) {
        this.num = n;
    }

}

public static void main(String[] args) {

    Number n1 = new Number(1);

    System.out.println(n1);
    changeNum(n1);
    System.out.println(n1);
    setNum(n1);
    System.out.println(n1);

}

public static void setNum(Number number) {
    number.setNum(999);
}

public static void changeNum(Number number) {
    number = new Number(111);
}

在探究问题之前,先来了解概念:

值传递: 值传递指的是在函数调用的时候将参数复制一份,这样在函数中的操作就对实际的参数没有影响;
引用传递:引用传递是将参数的地址传入函数操作,这样在函数操作的时候就会改变实际参数;

所以值传递较引用传递的区别是:
值传递会创建一个副本(复制一份),而引用传递不会创建副本;
接下来注意,由于上述的区别,造成的两者的不同是:
创建了副本的不会对原副本造成影响,而没有创建副本的会对元数据有影响;

那么我们区分值传递还是引用传递的根本是看它到底有没有复制副本;而会不会对实际参数造成影响是有没有创建副本带来的后果;

接下来看上面的代码:
为什么setNum()可以改变对象的值,而changeNum()却不行呢?因为java并不是简单的把对象复制了一份传入函数,而是将对象的引用复制了一份传入函数。也就是说在函数调用的时候,实际对象还是只有一个,但是它有2个引用,一个是本身的引用,另一个是调用函数的时候引用的复制,这2个引用都指向这个对象。所以就造成了上述情况。
setNum()的内部实际操作是改变属性,引用是没有属性的,要改变的是引用指向的对象的属性,他们指向的是同一个对象,那这个操作就会修改实际对象。
changeNum()就不一样了,它做的是改变引用的指向,但是这个引用并不是原来实际对象的引用,而是一个复制的引用,复制的引用出了函数就不存在了,所以不会对实际对象有所改变;

最后在回到开始的问题: 为什么java是值传递?这里答案已经很明显了,java对参数的处理是复制了一份实际参数的引用,而值传递的特点就是会复制一个副本,所以这就是值传递,只不过有点特殊(没有直接复制参数);也许你还会说: 它传递的就是一个引用啊,只不过是复制过的引用,也是引用啊,这是引用传递。这里就突出了一个概念的重要性,不是说传递的是引用就是引用传递,而是看概念,既然它创建了一个副本,这就不符合引用传递的概念,所以从概念上说,这时值传递。不过要是抛开概念,要说是引用传递也没有什么问题,但是概念不就是让人不那么混淆而存在的嘛,既然已经有了定义,遵守它就好了。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1.什么是值传递,什么是引用传递 举一个列子:int num = 10,num存储的是10这个值, ...
    从入门到暴毙阅读 2,688评论 0 0
  • 第5章 引用类型(返回首页) 本章内容 使用对象 创建并操作数组 理解基本的JavaScript类型 使用基本类型...
    大学一百阅读 8,446评论 0 4
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 13,793评论 1 32
  • 这是16年5月份编辑的一份比较杂乱适合自己观看的学习记录文档,今天18年5月份再次想写文章,发现简书还为我保存起的...
    Jenaral阅读 7,876评论 2 9
  • 关于java中到底是值传递,还是引用传递,这个问题困扰了我很久,前段时间看了一遍文章,让我彻底的明白了,在这里我总...
    JayChen0阅读 3,012评论 0 4