【Java基础】基本类型的包装类作为参数传递是值传递还是引用传递

突然想到这个问题,然后做了下实验,下面以Integer来讲解,其他的忽略:

import java.util.Iterator;

/**
 * Created by lili on 15/9/24.
 */
public class TestNew {
    public static void main(String args[]){

        Integer i1 = 10;
        Integer i2 = 20;
        System.out.println(i1   + "   " + i2);
        change(i1,i2);
        System.out.println(i1   + "   " + i2);

        String s1 = new String("s1");
        String s2 = new String("s2");
        System.out.println(s1 + "   " + s2);
        change(s1, s2);
        System.out.println(s1   + "   " + s2);

        StringBuilder sb1 = new StringBuilder("sb1");
        StringBuilder sb2 = new StringBuilder("sb2");
        System.out.println(sb1   + "   " + sb2);
        change(sb1,sb2);
        System.out.println(sb1   + "   " + sb2);

    }

    public static void change(Integer i1, Integer i2){
        i1 = 100;
        i2 = 200;
    }

    public static void change(String i1, String i2){
        i1 = "ii1";
        i2 = "i22";
    }

    public static void change(StringBuilder i1, StringBuilder i2){
        i1.append("sbsbsb1");
        i2.append("sbsbsb2");
    }
}

运行结果:

10   20
10   20
s1   s2
s1   s2
sb1   sb2
sb1sbsbsb1   sb2sbsbsb2

Process finished with exit code 0

事实证明,只有StringBuilder是引用传递,其他的还是值传递。

按照常理,应该传递的是对象的地址,难道这里是因为做了自动装箱和拆箱,编译器帮你做了这个导致最后是值传递了?

带着这个问题首先去看了class文件的反编译代码:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

public class TestNew {
    public TestNew() {
    }

    public static void main(String[] var0) {
        Integer var1 = Integer.valueOf(10);
        Integer var2 = Integer.valueOf(20);
        System.out.println(var1 + "   " + var2);
        change(var1, var2);
        System.out.println(var1 + "   " + var2);
        String var3 = new String("s1");
        String var4 = new String("s2");
        System.out.println(var3 + "   " + var4);
        change(var3, var4);
        System.out.println(var3 + "   " + var4);
        StringBuilder var5 = new StringBuilder("sb1");
        StringBuilder var6 = new StringBuilder("sb2");
        System.out.println(var5 + "   " + var6);
        change(var5, var6);
        System.out.println(var5 + "   " + var6);
    }

    public static void change(Integer var0, Integer var1) {
        var0 = Integer.valueOf(100);
        var1 = Integer.valueOf(200);
    }

    public static void change(String var0, String var1) {
        var0 = "ii1";
        var1 = "i22";
    }

    public static void change(StringBuilder var0, StringBuilder var1) {
        var0.append("sbsbsb1");
        var1.append("sbsbsb2");
    }
}

源代码显示并没有做值传递的优化,因为如果做了,应该change中的参数会改为int,这样一来Integer对象会自动拆装为int进行值传递,一种自动装卸拆箱的代码示例如下:

 Integer integer = 11;
 integer += 9;

 /*
 Integer integer = Integer.valueOf(11);//自动装箱
 integer = Integer.valueOf((integer.intValue() + 9));//自动拆箱再装箱
  */

那究竟是什么原因呢?

带着这个问题,对程序进行了debug,看看传递的是否是对象地址。

进入change方法后,看地址的变化

发现传入的是地址值,change参数的i1和i2的对象指向[email protected]和[email protected],说明指向和传入参数的同一个对象,传入的是地址。

接着执行方法change程序:

执行改变i1的值时,此时i1指向的对象改为了[email protected],至此可以充分说明不是自动装箱和拆箱的问题了,但是究其原因,我的理解还是和这个相关,因为执行到这一步的时候是i1 = 100;但是具体编译器优化后做了自动装箱处理,var0 = Integer.valueOf(100);所以i1指向了Integer.valueOf(100)这个新产生的对象,所以最后和值传递的效果一样,不会改变调用该方法的参数的值。

时间: 2024-10-13 11:12:53

【Java基础】基本类型的包装类作为参数传递是值传递还是引用传递的相关文章

java中参数传递--值传递,引用传递

java中的参数传递--值传递.引用传递 参数是按值而不是按引用传递的说明 Java 应用程序有且仅有的一种参数传递机制,即按值传递. 在 Java 应用程序中永远不会传递对象,而只传递对象引用.因此是按引用传递对象.Java 应用程序按引用传递对象这一事实并不意味着 Java 应用程序按引用传递参数.参数可以是对象引用,而 Java 应用程序是按值传递对象引用的. Java 应用程序中的变量可以为以下两种类型之一:引用类型或基本类型.当作为参数传递给一个方法时,处理这两种类型的方式是相同的.两

JAVA随笔篇二(深入分析JAVA简单类型、String和对象的值传递和引用传递)

关于JAVA的值传递和引用传递,翻看了很多资料和博客,感觉大多数讲的很乱,都是自己明白了之后就不讲了的样子,终于算是比较理解这几个概念了,下面做一个总结. 1.简单类型的参数传递 Java方法的参数是简单类型的时候,是按值传递的 (pass by value).下面举一个经典的swap函数: 无法交换值的方法: package TestTransferPack; public class TestTransfer { public static void main(String[] args)

java中方法的参数传递机制(值传递还是引用传递)

看到一个java面试题: 问:当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?  答:是值传递.Java 编程语言只有值传递参数.当一个对象实例作为一个参数被传递到方法中时,参数的值就是该对象的引用一个副本.指向同一个对象,对象的内容可以在被调用的方法中改变,但对象的引用(不是引用的副本)是永远不会改变的. 以下是从其他文章里转的,只为加深理解 public class TempTest { private void te

第002弹:Java 中的值传递和引用传递

在 Java 的代码开发过程中,为了尽可能提高方法的复用性,明确方法的作用,同时防止一个方法内部过于臃肿的问题,往往会创建许多方法,那么不可避免地会涉及到参数传递的问题.通常来说,我们将 Java 中的参数传递分为两种:值传递和引用传递. 值传递:参数在进入方法时,将入参深度复制一个副本,在方法内部操作的是入参的副本,在方法执行完毕之后,外部的入参没有发生任何变化. 引用传递:在方法内部操作的是参数本身,对入参做出的修改会保留到方法的外部. 那么在 Java 中,哪些情况属于值传递,哪些情况属于

java中的值传递和引用传递区别

值传递:(形式参数类型是基本数据类型):方法调用时,实际参数把它的值传递给对应的形式参数,形式参数只是用实际参数的值初始化自己的存储单元内容,是两个不同的存储单元,所以方法执行中形式参数值的改变不影响实际参数的值. 引用传递:(形式参数类型是引用数据类型参数):也称为传地址.方法调用时,实际参数是对象(或数组),这时实际参数与形式参数指向同一个地址,在方法执行中,对形式参数的操作实际上就是对实际参数的操作,这个结果在方法结束后被保留了下来,所以方法执行中形式参数的改变将会影响实际参数. 测试总结

JAVA不可变类与可变类、值传递与引用传递深入理解

一个由try...catch...finally引出的思考,在前面已经初步了解过不可变与可变.值传递与引用传递,在这里再次深入理解. 1.先看下面一个try..catch..finally的例子: Person.java package cn.qlq.test; public class Person { private int age; private String name; public int getAge() { return age; } public void setAge(int

这一次,彻底解决Java的值传递和引用传递

本文旨在用最通俗的语言讲述最枯燥的基本知识 学过Java基础的人都知道:值传递和引用传递是初次接触Java时的一个难点,有时候记得了语法却记不得怎么实际运用,有时候会的了运用却解释不出原理,而且坊间讨论的话题又是充满争议:有的论坛帖子说Java只有值传递,有的博客说两者皆有:这让人有点摸不着头脑,下面我们就这个话题做一些探讨,对书籍.对论坛博客的说法,做一次考证,以得出信得过的答案. 其实,对于值传递和引用传递的语法和运用,百度一下,就能出来可观的解释和例子数目,或许你看一下例子好像就懂,但是当

堆栈详解 + 彻底理解Java的值传递和引用传递

本文旨在用最通俗的语言讲述最枯燥的基本知识 学过Java基础的人都知道:值传递和引用传递是初次接触Java时的一个难点,有时候记得了语法却记不得怎么实际运用,有时候会的了运用却解释不出原理,而且坊间讨论的话题又是充满争议:有的论坛帖子说Java只有值传递,有的博客说两者皆有:这让人有点摸不着头脑,下面我们就这个话题做一些探讨,对书籍.对论坛博客的说法,做一次考证,以得出信得过的答案. 其实,对于值传递和引用传递的语法和运用,百度一下,就能出来可观的解释和例子数目,或许你看一下例子好像就懂,但是当

Java中的值传递和引用传递

解释 1.Java中有没有引用传递? 答:Java中只有按值传递,没有按引用传递! 2.当一个对象被当作参数传递到一个方法中后,在此方法中可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递? 答:是值传递. Java参数,不管是原始类型还是引用类型,传递的都是副本(有另外一种说法是传值,但是说传副本更好理解吧,传值通常是相对传址而言).如果参数类型是原始类型,那么传过来的就是这个参数的一个副本,也就是这个原始参数的值,这个跟之前所谈的传值是一样的,如果在函数中改变了副本