java中的传递参数其实都是值传递(引用就是拷贝对象的一个地址)

               其实java函数中的参数都是传递值的,所不同的是对于基本数据类型传递的是参数的一份拷贝,对于类类型传递的是该类参数的引用的拷贝,当在函数体中修改参数值时,无论是基本类型的参数还是引用类型的参数,修改的只是该参数的拷贝,不影响函数实参的值,如果修改的是引用类型的成员值,则该实参引用的成员值是可以改变的,例子如下。

首先是定义改变参数的
       public static void changeInt(inti){//改变int型变量的函数
                i=100;
         }
     public static void changeString(Strings){//改变String型变量的函数
                s="changeString";
         }
      public static void changeModel(Modelmodel){//改变Model型变量的函数
                model=new Model();
                model.i=1;
                model.s="changeModel";
        }
       public static void changeModel2(Modelmodel){//改变Model型变量的成员的函数
                model.i=1;
                model.s="changeModel";
       }

       类Model

        class Model{
                          public int i=0;
                           public String s="no value";
        }

测试程序
      public static void main(String[]args) {
                int i=0;
                String s="hello";
               Model model=new Model();
               Model model2=new Model();
               changeInt(i);
               System.out.println("i="+i);
               changeString(s);
               System.out.println("s="+s);
               changeModel(model);
               System.out.println("model:"+model.s);
               changeModel2(model2);
               System.out.println("model2:"+model2.s);

}

   测试结果:
                  i=0
                  s=hello
                  model:no value
                  model2:changeModel
可以看出i没有改变,s也没有改变,mode也没有改变,model2的s改变了。

总结:java中的形参是复制实参的一份拷贝(对于引用型则是复制引用的拷贝)(在栈中的拷贝),所以在函数中改变形参是无法改变实参的值的,改变引用只是将形参所代表的引用指向另外的新的对象,而实参的引用还指向原来的对象,改变形参引用的成员当然会影响实参引用成员的值,因为他们的引用都指向同一个对象

Java中String是“引用”传递

如题,在java中这是一个典型的问题。 在stackoverflow上已经有很多相似的问题被提问,并且有很多不正确或不完整的答案。如果你不往深处想,这是一个很简单的问题。但如果深入思考,它却很让人迷惑。

1. 下面是一段很有意思并且让人迷惑的代码

1
2
3
4
5
6
7
8
9
public static void main(String[] args) {
     String x = new String( "ab" );
     change(x);
     System.out.println(x);
}
  
public static void change(String x) {
     x = "cd" ;
}

运行它将打印 “ab”.

2. 通常让人迷惑的解释如下

在java堆中x存储指向“ab”的引用。所以当x作为参数传递给change()方法时,它在内存中仍然指向“ab”,如下:


由于java是值传递,所以此时x仍然指向“ab”。当chang()方法执行时,它在内存中创建了一个新的String对象“cd”,并且现在x指向“cd”,如下:


上面的解释看起来非常合理。他们也很清楚java是值传递。但是哪里出错了?


3. 上面的代码到底如何执行的呢?

上面的解释有几处错误。跟踪代码执行全过程是一个很好的方法,并且理解起来很容易。

当“ab”创建后,java分配对象所需内存空间。然后,变量x指向了“ab”,变量实际上是指向对象的引用。这个引用指向对象存储的地址。

x保存了一个指向String对象的地址。x不是引用本身!它是保存一个内存地址(x="cd",是在内存中创建了一个新的对象,并且赋值)。

在Java中只有值传递。当x通过参数传递给change()方法后,x被拷贝了一份。change()创建了另一个对象“cd”,并且x指向了不同的地址空间。实际上是x改变它的引用(指向“cd”),不是x本身。

下图展示了x在内存的变化


4. 错误的解释

上面的问题跟String的不可变没有关系。即使是StringBuilder,结果也一样。关键是变量存储的是引用,而不是引用本身!他饶啦

5. 解决问题

如果真的要改变对象的值。首先,对象应该是可变的,如StringBuilder,另外,我们要确认没有新对象生成并且赋予参数变量,因为java只有值传递

1
2
3
4
5
6
7
8
9
public static void main(String[] args) {
     StringBuilder x = new StringBuilder( "ab" );
     change(x);
     System.out.println(x);
}
  
public static void change(StringBuilder x) {
     x.delete( 0 , 2 ).append( "cd" );
}

猜你喜欢

转载自blog.csdn.net/qq_36753550/article/details/53862872