Java究竟是值传递还是引用传递?

2019-11-29  本文已影响0人  哥哥是头熊

Java里面永远都是值传递,没有引用传递,没有任何例外情况。

https://stackoverflow.com/questions/40480/is-java-pass-by-reference-or-pass-by-value

我们时常会觉得Java对于对象是引用传递,这是一个误解,因为Java语言的设计就是:我们无法直接操作对象,我们拿到的都是对象的引用,进而通过引用操作对象。

但是即使传递的是Java的引用,归根结底,传递的也是对象的地址,所以Java里面只有值传递。

近期在研究这个问题的时候,发现有很多文章会将 最终对象的值会不会改变作为是值传递还是引用传递的判断标准之一,这是不太妥当的。

我觉得较为准确的回答应该是:Java里面只有值传递,至于传递的对象会不会改变?这个得看情况

例子1:

String a = "alex";

public void operateStr(String str) {
  str = "bob";
}
public static void main(String[] args) {  
   operateStr(a);
}

这种情况下,a的值不会变
str一开始是获得a对象地址的一份拷贝,而a = "bob", 会在字符串池里创建一个新的对象,str变量又重新指向了字符串池里bob这个对象

例子2:

public class A {
  private String name;
  public void setName(String name) {
    this.name = name;
  }
  public void getName(String name) {
    return name;
  }
}
public class Test {
  public void operateA(A obj) {
    obj.setName("cara");
  }
  public static void main(String[] agrs) {
     A a = new A();
     a.setName("doly");
     new Test().operateA(a);
  }
}

这种情况下,a的name会变,改变了对象的成员变量

例子3:

public class A {
  private String name;
  public void setName(String name) {
    this.name = name;
  }
  public void getName(String name) {
    return name;
  }
}
public class Test {
  public void operateA(A obj) {
    obj = new A();
    obj.setName("cara");
  }
  public static void main(String[] agrs) {
     A a = new A();
     a.setName("doly");
     new Test().operateA(a);
  }
}

例子4:

这种情况下,a的name不会变,因为操作的都是方法里新建的对象,原来的对象没有发生任何改变。

public class A {
  private String name;
  public void setName(String name) {
    this.name = name;
  }
  public void getName(String name) {
    return name;
  }
}
public class Test {
  public A operateA(A obj) {
    obj = new A();
    obj.setName("cara");
    return obj;
  }
  public static void main(String[] agrs) {
     A a = new A();
     a.setName("doly");
     a = new Test().operateA(a);
  }
}

这种情况下,a的name会发生改变,因为变量a指向了方法里新创建的对象。

补充1:

关于字符串,字符串有个常量池,这个具体介绍请看另外一篇 " "与new String(" ")的区别

补充2:

Java中栈内存比较快,堆内存比较慢
栈有一个很重要的特殊性,就是存在栈中的数据可以共享。

int a = 3;
int b = 3;
a = 4;

对于基本类型,是存在栈里面的,编译器在处理int a = 3,先在栈里创建一个变量为a的引用,如果栈里没有3,先将3存进来,然后将a指向3,创建b的引用时,因为栈里已经有3,这个时候直接将b指向3,a和b会同时指向3。
如果再令a=4,同样会查找栈里面有没有4,如果没有,将4存进来,同时将a指向4,如果已经有了,直接将a指向这个地址,因此对a的影响不会改变b的值。
但是这里的数据共享与两个引用同时指向一个对象是不同的,对a的改变不会影响b的值,由编译器完成,有利于节省空间。

上一篇 下一篇

猜你喜欢

热点阅读