首页 > 编程语言 >Java是值传递还是引用传递,又是怎么体现的

Java是值传递还是引用传递,又是怎么体现的

时间:2024-09-07 16:51:59浏览次数:12  
标签:Java 打印 System 传递 person 引用 println identityHashCode out

关于Java是值传递还是引用传递,可以从代码层面来实现一下拿到结果
执行下面的代码:

    public static void main(String[] args) {
        int num = 10;
        String name = "Tom";
        modify(num, name);
        System.out.println("第3次打印int:" + num);
        System.out.println("第3次打印String:" + name);
        System.out.println("------------------------------------");
    }

    public static void modify(int n, String str){
        System.out.println("第1次打印int:" + n);
        System.out.println("第1次打印String:" + str);
        System.out.println("------------------------------------");

        // 尝试在方法内部修改传进来的参数
        n = 999;
        str = "ABC";
        System.out.println("第2次打印int:" + n);
        System.out.println("第2次打印String:" + str);
        System.out.println("------------------------------------");
    }

打印出来的结果如下:

第1次打印int:10
第1次打印String:Tom
------------------------------------
第2次打印int:999
第2次打印String:ABC
------------------------------------
第3次打印int:10
第3次打印String:Tom
------------------------------------

可以看到无论是基本类型还是引用类型,传参数进去的时候的值和执行完modify方法后的值是一样的,也就是第1次打印和第三次打印是一样的。可是为什么明明在第2次已经修改成功了,第3次却又变回去了呢?
尝试换个方法把参数拿出来,

    public static void main(String[] args) {
        int num = 10;
        String name = "Tom";
        int modifiedNum = modifyAndReturn(num);
        String modifiedName = modifyAndReturn(name);
        System.out.println("打印num:" + num);
        System.out.println("打印name:" + name);
        System.out.println("------------------------------------");
        System.out.println("打印modifiedNum:" + modifiedNum);
        System.out.println("打印modifiedName:" + modifiedName);
    }

    public static int modifyAndReturn(int n){
        System.out.println("modifyAndReturn第1次打印int:" + n);

        // 尝试在方法内部修改传进来的参数
        n = 999;
        System.out.println("modifyAndReturn第2次打印int:" + n);
        System.out.println("------------------------------------");
        return n;
    }

    public static String modifyAndReturn(String str){
        System.out.println("modifyAndReturn第1次打印String:" + str);

        // 尝试在方法内部修改传进来的参数
        str = "ABC";
        System.out.println("modifyAndReturn第2次打印String:" + str);
        System.out.println("------------------------------------");
        return str;
    }

得到的结果为

modifyAndReturn第1次打印int:10
modifyAndReturn第2次打印int:999
------------------------------------
modifyAndReturn第1次打印String:Tom
modifyAndReturn第2次打印String:ABC
------------------------------------
打印num:10
打印name:Tom
------------------------------------
打印modifiedNum:999
打印modifiedName:ABC

可以看到通过return出来的值,的确是被改变了的,那又是为什么导致这个改变没有应用到参数本体呢?修改下代码再次测试

public static void main(String[] args) {
        int num = 10;
        String name = "Tom";
        // 打印num和str的地址
        System.out.println("修改前,传参前:");
        System.out.println(System.identityHashCode(num));
        System.out.println(System.identityHashCode(name));

        System.out.println("---------------------------");
        printAddr(num, name);

        System.out.println("---------------------------");
        System.out.println("修改后,执行完方法后:");
        System.out.println(System.identityHashCode(num));
        System.out.println(System.identityHashCode(name));
    }

    public static void printAddr(int n, String str){
        // 打印n和str的地址
        System.out.println("修改前,传参后:");
        System.out.println(System.identityHashCode(n));
        System.out.println(System.identityHashCode(str));

        n = 999;
        str = "ABC";

        // 打印n和str的地址
        System.out.println("---------------------------");
        System.out.println("修改后,传参后:");
        System.out.println(System.identityHashCode(n));
        System.out.println(System.identityHashCode(str));
    }

执行结果如下

修改前,传参前:
1324119927
990368553
---------------------------
修改前,传参后:
1324119927
990368553
---------------------------
修改后,传参后:
1096979270
1078694789
---------------------------
修改后,执行完方法后:
1324119927
990368553

可以看到传参进来的参数地址是和外部定义的地址是同一个,但是修改之后会指向另一个新的地址,导致原来地址上的数据不会受到影响,这其实是一个保护机制,防止参数传入方法内被篡改指向。

下面演示引用类型的另一种情况,一些老铁可能以为是对引用类型本身的修改,其实这是不对的。
先定义一个类Person

class Person{
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = 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;
    }

	@Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }	
}

执行下面的代码,可以看到传进去的参数的属性被改变


    public static void main(String[] args) {
        Person person = new Person("Rosy", 24);
        String [] strings = {"AAA", "BBB", "CCC"};
        System.out.println("第1次打印:");
        System.out.println(person);
        System.out.println(Arrays.toString(strings));

        modifyObjAndPrintValue(person, strings);

        System.out.println("---------------------------");
        System.out.println("第4次打印:");
        System.out.println(person);
        System.out.println(Arrays.toString(strings));
    }

    public static void main5(String[] args) {
        Person person = new Person("Rosy", 24);
        String [] strings = {"AAA", "BBB", "CCC"};
        System.out.println("第1次打印:");
        System.out.println(System.identityHashCode(person));
        System.out.println(System.identityHashCode(person.getAge()));
        System.out.println(System.identityHashCode(person.getName()));
        System.out.println(System.identityHashCode(strings));

        modifyObj(person, strings);

        System.out.println("---------------------------");
        System.out.println("第4次打印:");
        System.out.println(System.identityHashCode(person));
        System.out.println(System.identityHashCode(person.getAge()));
        System.out.println(System.identityHashCode(person.getName()));
        System.out.println(System.identityHashCode(strings));
    }

    public static void modifyObjAndPrintValue(Person person, String [] strings){
        System.out.println("---------------------------");
        System.out.println("第2次打印:");
        System.out.println(person);
        System.out.println(Arrays.toString(strings));

        person.setAge(1024);
        person.setName("ABC");
        strings[0] = "XXX";

        System.out.println("---------------------------");
        System.out.println("第3次打印:");
        System.out.println(person);
        System.out.println(Arrays.toString(strings));
    }

执行结果为

第1次打印:
Person{name='Rosy', age=24}
[AAA, BBB, CCC]
---------------------------
第2次打印:
Person{name='Rosy', age=24}
[AAA, BBB, CCC]
---------------------------
第3次打印:
Person{name='ABC', age=1024}
[XXX, BBB, CCC]
---------------------------
第4次打印:
Person{name='ABC', age=1024}
[XXX, BBB, CCC]

从结果可以发现,Person对象的属性都被修改,String数组的元素也被修改,说明参数里对属性或数组的修改是会影响对象本身的,具体可以打印地址再查看一下:


    public static void main(String[] args) {
        Person person = new Person("Rosy", 24);
        String [] strings = {"AAA", "BBB", "CCC"};
        System.out.println("第1次打印:");
        System.out.println(System.identityHashCode(person));
        System.out.println(System.identityHashCode(person.getAge()));
        System.out.println(System.identityHashCode(person.getName()));
        System.out.println(System.identityHashCode(strings));
        System.out.println(System.identityHashCode(strings[0]));

        modifyObjAndPrintAddr(person, strings);

        System.out.println("---------------------------");
        System.out.println("第4次打印:");
        System.out.println(System.identityHashCode(person));
        System.out.println(System.identityHashCode(person.getAge()));
        System.out.println(System.identityHashCode(person.getName()));
        System.out.println(System.identityHashCode(strings));
        System.out.println(System.identityHashCode(strings[0]));
    }


    public static void modifyObjAndPrintAddr(Person person, String [] strings){
        System.out.println("---------------------------");
        System.out.println("第2次打印:");
        System.out.println(System.identityHashCode(person));
        System.out.println(System.identityHashCode(person.getAge()));
        System.out.println(System.identityHashCode(person.getName()));
        System.out.println(System.identityHashCode(strings));
        System.out.println(System.identityHashCode(strings[0]));

        person.setAge(1024);
        person.setName("ABC");
        strings[0] = "XXX";

        System.out.println("---------------------------");
        System.out.println("第3次打印:");
        System.out.println(System.identityHashCode(person));
        System.out.println(System.identityHashCode(person.getAge()));
        System.out.println(System.identityHashCode(person.getName()));
        System.out.println(System.identityHashCode(strings));
        System.out.println(System.identityHashCode(strings[0]));
    }
第1次打印:
990368553
1096979270
1078694789
1831932724
1747585824
---------------------------
第2次打印:
990368553
1096979270
1078694789
1831932724
1747585824
---------------------------
第3次打印:
990368553
1023892928
558638686
1831932724
1149319664
---------------------------
第4次打印:
990368553
2093631819
558638686
1831932724
1149319664

从地址上可以看到,person和strings的地址一直没有变过。而在参数内部修改的person属性和数组元素,会对这部分成员的地址进行修改,并且会应用到对象本体上。

总结下来就是,无论传的是基本类型还是引用类型,只要在方法内部尝试改变参数地址的,都只能在方法内部使用,不会影响本体,而在方法内部改变属性的,会把对应的改变应用到本体上。所以Java是值传递的,传参的时候并不是把本身传入,而是创建一个副本,当被修改指向的时候不会影响本身,修改属性由于不会修改本身的地址,因此的时候可以应用到本体上。

标签:Java,打印,System,传递,person,引用,println,identityHashCode,out
From: https://www.cnblogs.com/huajieyu/p/18401887

相关文章

  • MASM32+ HTML & JavaScript,好搭档
    哪个编程工具让你的工作效率翻倍?在日益繁忙的工作环境中,选择合适的编程工具已成为提升开发者工作效率的关键。不同的工具能够帮助我们简化代码编写、自动化任务、提升调试速度,甚至让团队协作更加顺畅。那么,哪款编程工具让你的工作效率翻倍?是智能的代码编辑器,强大的版本控制工具,还是......
  • java入门笔记2(类和对象到接口)
    类和对象最简单的类packagestudy;publicclasstest1{publicintbrand;publicStringname;publicvoidread(){System.out.println(brand+"book");}publicvoideat(inta){System.out.println(name+"eat&quo......
  • LeetCodeTest算法测试 传递一个数组和一个特定的目标整型数字,返回的两个数组元素相加
    1importjava.util.ArrayList;2importjava.util.List;34publicclassLeetCodeTest{5publicstaticvoidmain(String[]args){67int[]intArr=newint[]{2,7,11,15};8List<CustomerIntIndex>customerIntIndexL......
  • Java IO流详解:像流水一样读写数据
    JavaIO流详解:像流水一样读写数据在Java编程世界中,IO流就像水流一样,不断地在内存和外部存储之间搬运数据。这些数据流可以是字节,也可以是字符。不管是文件读写、网络传输,还是数据处理,IO流总是无处不在。下面我们就来揭开IO流的面纱,看看它是如何工作的,以及在实际开发中有哪些应用......
  • Java 通过aspose.words 把docx文件转成pdf文件后中文变成小方块,aspose转pdf乱码问题的
    Java通过aspose.words把docx文件转成pdf文件后中文变成小方块,aspose转pdf乱码问题的解决方法一、问题描述​在centos服务器使用aspose.word转换word文件为pdf的时候显示中文乱码,但是在win服务器上使用可以正常转换二、问题原因由于linux服务器缺少对应的字库导致文件转换出现......
  • java+vue计算机毕设城市应急救援辅助系统【源码+开题+论文+程序】
    本系统(程序+源码)带文档lw万字以上文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着城市化进程的加速,城市人口密集度不断提高,各类突发灾害与紧急事件的风险也随之增加。自然灾害如地震、洪水,以及人为事故如火灾、交通事故等,均对城......
  • java+vue计算机毕设宠物购物系统【源码+开题+论文+程序】
    本系统(程序+源码)带文档lw万字以上文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景在当今社会,随着人们生活水平的提高和情感需求的多样化,宠物已成为许多家庭不可或缺的重要成员。宠物的养护与陪伴不仅丰富了人们的情感世界,也带动了宠......
  • java+vue计算机毕设宠物交易平台【源码+开题+论文+程序】
    本系统(程序+源码)带文档lw万字以上文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着社会经济的快速发展和人们生活水平的提高,宠物已成为许多家庭不可或缺的重要成员。宠物市场的繁荣不仅体现在宠物数量的激增上,更在于宠物相关服务......
  • java+vue计算机毕设宠物领养系统【源码+开题+论文+程序】
    本系统(程序+源码)带文档lw万字以上文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着城市化进程的加速,人类生活与宠物之间的联系日益紧密,但同时也带来了流浪宠物数量激增的社会问题。流浪宠物不仅面临着生存的挑战,还可能成为疾病传......
  • json字符串转义格式化后再转换处理demo StringEscapeUtils.unescapeJava
    json字符串转义格式化后再转换处理demoStringEscapeUtils.unescapeJava报错关键字:illegalidentifierExpectedBEGIN_OBJECTbutExpectednameatpackagecom.example.core.mydemo;importcom.alibaba.fastjson.JSON;importcom.fasterxml.jackson.core.JsonProcessingE......