美文网首页
Java 参数传递

Java 参数传递

作者: 南风nanfeng | 来源:发表于2017-09-08 15:10 被阅读109次

    Java方法传参方式记住了两点。基本上不会犯错误。

    1. 方法内修改基础数据类型(数字类型或布尔类型)不会改变方法外的参数;
    2. 方法内修改对象(包含数组)状态会同步修改方法方法外的参数。

    程序片段1来验证第一点:
    public static void main(String[] args) {
        Integer a = 5;
        System.out.println("入栈前 a = " + a);
        calc(a);
        System.out.println("出栈后 a = " + a);    
     }
    private static void calc(Integer a) {
        a = a * 3;
        System.out.println("栈内计算 a = " + a);
    }
    
    程序的运行结果为:
    入栈前 a = 5
    栈内计算 a = 15
    出栈后 a = 5
    

    程序片段2来验证第二点
    public static void main(String[] args) {
        Stu tom = new Stu(30, "tom");
        System.out.println("入栈前 tom = " + tom);
        doubleScore(tom);
        System.out.println("出栈后 tom = " + tom);
    
    }
    
    private static void doubleScore(Stu tom) {
        tom.score = tom.score * 2;
        System.out.println("栈内计算 tom = " + tom);
    }
    
    private static class Stu {
        String name;
        int score;
        public Stu(int score, String name) {
            this.score = score;
            this.name = name;
        }
        @Override
        public String toString() {
            return "[ name='" + name + '\'' + ", score=" + score + ']';
        }
    }
    
    片段2的运行结果为:
    入栈前 tom = [ name='tom', score=30]
    栈内计算 tom = [ name='tom', score=60]
    出栈后 tom = [ name='tom', score=60]
    

    从两段程序的结果看,片段1的基础数据参数用值传递来解释的通;片段2的对象参数用引用传递也行的通。

    究竟参数传递采用哪种方式呢,特地翻了 Java编程思想第四版 第12章 传递和返回对象 中给出了解释,Java中所有参数或自变量都是通过句柄的方式传递的,向方法中传递一个参数时,实际上传递的只是指向外部对象的一个句柄。

    看清楚了吗,人家根本不关心什么值传递、引用传递,实际上问题的关键是怎么理解 句柄

    • Java按值传递任何东西。句柄当做指针,传递对象就是拷贝对象的地址值,参数也指向该对象,方法内对象状态改外部对象也会改变;基础数据类型就更明显,基础数据传入方法会得到一个数据的副本,所以一切传参都是按值传递。
    • Java主要按值传递,但对象却是引用传递。句柄看做对象的一个“别名”,由于对象传入方法没有获得一个本地副本,所以对象传递显然不是值传递,而是引用传递。
      句柄 的理解不同带来了不同的结果,原书的作者直接回避了这个问题,也许java的设计者压根没有考虑这个问题,才会后面的争议。

    还有一点一定要记住,记为第三点:
    1. 方法不能改变对象参数的引用
    程序片段3来验证第3点:
    public static void main(String[] args) {
        Stu tom = new Stu(30, "tom");
        System.out.println("入栈前 tom = " + tom);
        convert(tom);
        System.out.println("出栈后 tom = " + tom);
    }
    private static void convert(Stu tom) {
        tom = new Stu(50, "jack");
        System.out.println("栈内计算 tom = " + tom);
    }
    
    程序片段3来运行结果:
    入栈前 tom = [ name='tom', score=30]
    栈内计算 tom = [ name='jack', score=50]
    出栈后 tom = [ name='tom', score=30]
    

    总结

    不管一切按值传递,还是主要按值传递,从这三个特点来讲都解释的通,没必要为概念纠结,明白特性才是关键!

    相关文章

      网友评论

          本文标题:Java 参数传递

          本文链接:https://www.haomeiwen.com/subject/dadwjxtx.html