Java是引用传递还是值传递?

突然想起自己在刚学Java的时候,成员变量名和方法参数名相同时,我搞不清楚set方法中的this到底是指的哪个值。想想真的挺搞笑的,但是当时确实就是想不明白,哈哈。这种类似傻傻分不清的问题,Java的传递问题算一个,今天来总结一下。

直接先解答问题:
在Java中方法参数传递的方式是按值传递的。
参数是基本类型,传递的是基本类型的字面量值的拷贝。
参数是引用类型,传递的是所引用的对象在堆中地址值的拷贝。
或者有的更官方一点的说法叫:Java函数调用时采用的求值策略为值传递。

如果你理解上面的几句话,那么基本没什么问题了,如果不太懂,那么请往下看,直接上代码和图:


class MainTest {

    public static void main(String[] args) {
        int count = 3;
        changeNumber(count);
        System.out.println(count);

        String content = "科比";
        changeString(content);
        System.out.println(content);

        SportsMan sportsMan = new SportsMan("科比");
        changeObject(sportsMan);
        System.out.println(sportsMan.name);

        List list = new ArrayList<>();
        list.add("一");
        list.add("二");
        changeObjectValue(list, sportsMan);
        for (String str : list) System.out.print(str);
        System.out.println("\n" + sportsMan.name);
    }

    private static void changeNumber(int count) {
        count += 10;
    }

    private static void changeString(String content) {
        content += "投进一个三分球";
    }

    private static void changeObject(SportsMan sportsMan) {
        sportsMan = new SportsMan("艾弗森");
    }

    private static void changeObjectValue(List list, SportsMan sportsMan) {
        list.add("三");
        sportsMan.name = "哈登";
    }

    private static class SportsMan {
        String name;
        public SportsMan(String name) {
            this.name = name;
        }
    }

}

运行结果:
3
科比
科比
一二三
哈登

上图:
在这里插入图片描述

理解上面代码的结果,我们要明白两个概念:实参和形参。
形参是作为实参的一个拷贝,我们可以直接看到前三个方法传递进来的值,直接显示为灰色,其实这些值的改变是对原值无影响的。
image.png
其实就是一个很简单的问题,说的生动一些吧,我用播音员拿稿子打一个比方:
我们将参数传入方法当中比做——有人往播音室递了一张纸
实参——原稿件
形参——这张纸
参数是基本类型,字面量的拷贝——直接在纸上写着稿子
参数是引用类型,引用地址的拷贝——纸上写着保存这个稿子的文档地址(比如腾讯文档)
纸上面写着稿子,无论你在这张纸怎么改,都不会影响到原来的稿子
纸上面写着文档地址,你把文档里面的稿子改了,原稿件也就跟着改了
把纸上面的文档地址换成了另一个稿件的文档地址,那原稿件内容肯定是不变的

那么就有了这一道面试题:

以下程序输出结果是什么:
public class Point {
    private int x;
    private int y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public void setLocation(int x, int y) {
        this.x = x;
        this.y = y;
    }

    private static void modifyPoint(Point p1, Point p2) {
        Point tmpPoint = p1;
        p1 = p2;
        p2 = tmpPoint;
        p1.setLocation(5, 5);
        p2 = new Point(5, 5);
    }

    public static void main(String[] args) {
        Point p1 = new Point(0, 0);
        Point p2 = new Point(0, 0);
        modifyPoint(p1, p2);
        System.out.println("[" + p1.x + "," + p1.y + "],[" + p2.x + "," + p2.y + "]");
    }

}

先自己看一下,一会再看答案。































查看答案
[0,0],[5,5]

主要是看modifyPoint方法:

	 private static void modifyPoint(Point p1, Point p2) {
	 	// tmpPoint引用着形参p1的地址,也就是main方法中实参p1的地址
        Point tmpPoint = p1;
        // p1引用着形参p2的地址,也就是main方法中实参p2的地址
        p1 = p2;
        // p2引用着形参p1的地址,也就是main方法中实参p1的地址,熟悉的味道,就是互相交换了一下
        p2 = tmpPoint;
        // 此时形参p1引用的是main方法中的实参p2的地址
        // 形参p2引用的是main方法中的实参p1的地址
        // 给形参p1修改了location,那么修改的就是main方法中实参p2的location
        p1.setLocation(5, 5);
        // 形参p2的引用变为了一个新的对象,那么原来的对象,main方法中的实参p1的属性不变
        p2 = new Point(5, 5);
		// 所以最终main方法中p1的location仍是(0,0), p2的location变为了(5,5)
    }

总结

其实我觉得值引用的这个问题,是一个很实在的问题,我们在实际的开发中难免会遇到各种基本类型、对象以及方法传参的问题。如果对值引用还很模糊的话,在开发中一旦出现问题我们会感到很莫名其妙,然后再花大量的时间去解决这些原本很基础的问题,真的是得不偿失。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值