V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
857681664
V2EX  ›  程序员

关于 Java 函数参数引用类型的问题

  •  
  •   857681664 ·
    zshnb · 2022-10-30 18:30:38 +08:00 · 1021 次点击
    这是一个创建于 534 天前的主题,其中的信息可能已经有所发展或是发生改变。

    印象中记得 java 的参数传递方式是引用传递,但是为什么对于基本类型在函数里的参数修改不会影响到函数外传入的变量呢,是因为对于基本类型来说,值就存储在变量本身了吗,还是说基本类型的值是存在栈上,只不过随着函数调用,参数压栈后,对应的值也会跟着参数复制一份,对参数本身的修改就不会影响到函数外传入的值,而对象参数是指向堆的一个地址,即使复制了,也是同一个地址,因此在函数内修改参数对象的值会影响函数外传入的对象值。

    如果想要让 java 也能做到类似 C 语言的解引用,类似 int* aAddr = &b,是不是只要让栈地址暴露出去就可以了。

    public class Reference {
    
        public static void main(String[] args) {
            Reference reference = new Reference();
            Student student = new Student(1);
            System.out.printf("before change student's age: %d\n", student.age);
            reference.changeReference(student);
            System.out.printf("after change student's age: %d\n", student.age);
    
            int a = 1;
            System.out.printf("before change int: %d\n", a);
            reference.changePrimitive(a);
            System.out.printf("after change int: %d\n", a);
        }
    
        void changeReference(Student s) {
            s.age += 1;
        }
    
        void changePrimitive(int a) {
            a = 2;
        }
    
        static class Student {
            int age;
    
            public Student(int age) {
                this.age = age;
            }
        }
    }
    
    
    5 条回复    2022-10-31 09:36:42 +08:00
    Jooooooooo
        1
    Jooooooooo  
       2022-10-30 18:35:39 +08:00
    java 是值传递, 对象传的是指针.

    基本类型在 java 里确实特殊, 和对象不是一回事
    857681664
        2
    857681664  
    OP
       2022-10-30 18:45:26 +08:00
    正文里说错了,应该是值传递,刚才又想到,对于基本类型和对象的 print 也会显示不一样的行为,基本类型打印值,对象打印的是堆地址,是不是 java 的基本类型没有地址这一说法,还是 jvm 把基本类型的地址隐藏起来了。
    cpstar
        3
    cpstar  
       2022-10-30 20:15:04 +08:00
    可以理解基本类型在 java 中是异类,所有就解释通了。为什么要用异类的 int 而不用对象 Integer ,想通了?

    至于输出和使用等等,如果你了解 JVM 的原理,那就根本不会存在到底是引用还是值这个概念,存入的都是值,只不过指令类型不一样。比如 int 的 add 会翻译成 iadd ,然后后边的两个操作数直接相加,而 Integer 的 add 则会一系列 aload 和 invokevirtual 。
    换句话,如果在 bytecode 层面,把 iadd 换成了 invokevirtual ,那就会可能产生你说的 int* aAddr = &b 效果,比如我曾经在 bytecode 层面做出 boolean t; if (t>=0)这样的操作。
    snailsir
        4
    snailsir  
       2022-10-31 09:33:37 +08:00
    snailsir
        5
    snailsir  
       2022-10-31 09:36:42 +08:00
    或者看微信公众号发的也行: https://mp.weixin.qq.com/s/h8JW3H1KMS9DXFgGYiwJJg
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   958 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 21:50 · PVG 05:50 · LAX 14:50 · JFK 17:50
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.