java方法返回对象的副本还是对象的引用?

时间:2019-06-25 10:37:04

标签: java memory-management

public class UnderstandingMemoryManagement1 {

  private static boolean flag = false;

  public static void main(String[] args) {

    Set<String> mainNameSet = getNameSet();
    mainNameSet.add("Name-6");

    Log.logInfo(getNameSet() == mainNameSet);
    Log.logInfo(getNameSet().equals(mainNameSet));
    Log.logInfo("------main() END------");
  }
  public static Set<String> getNameSet() {

    Set<String> nameSet = new TreeSet<>();
    nameSet.add("Name-1");
    nameSet.add("Name-2");
    nameSet.add("Name-3");
    nameSet.add("Name-4");

    Set<String> otherSet = nameSet;
    otherSet.add("Name-5");

    if (!flag ) {

      flag = true;
      Log.logInfo(nameSet == otherSet);
      Log.logInfo(nameSet.equals(otherSet));
      Log.logInfo("------getNameSet() END------");
    }
    return nameSet;
  }
}

当我运行上面的代码时,为什么输出如下:-

INFO: true 
INFO: true 
INFO: ------getNameSet() END------ 
INFO: false 
INFO: false 
INFO: ------main() END------

为什么第二次返回false为何不为真? 据我所知,java复制了引用而不是对象。当它处理引用而不是对象时,对于第二种情况也应返回true。请给我解释一下。

2 个答案:

答案 0 :(得分:2)

方法getNameSet()每次被调用时都会返回对新TreeSet对象的引用。您在main()中调用此方法 3 次,因此得到三种不同的 TreeSet对象。

第一个false来自两个不同的TreeSet对象与==运算符的比较。这些是不同的对象,具有不同的参考值。

第二个false来自mainNameSet.add("Name-6");,它修改了第一个TreeSet,因此不再相等。

答案 1 :(得分:2)

您首先调用getNameSet()方法并将其结果存储到mainNameSet变量中。该方法包含一条语句,其中构造了一个新的TreeSet实例,然后您将返回此新实例:

Set<String> nameSet = new TreeSet<>();
...
return nameSet;

然后您要执行以下操作:

getNameSet() == mainNameSet

您再次 调用getNameSet(),这反过来构造了一个新的TreeSet实例并返回它。 对于每个getNameSet()呼叫,您都有不同的TreeSet实例

这就是为什么比较返回false的原因。


Java is always pass-by-value,如果是引用,则意味着复制了传递给方法的引用。

void handle(Dog inputDog) {
    inputDog = new Dog("Jack");
}
Dog myDog = new Dog("Fluffy");
handle(myDog);

// The name of the dog referenced by 'myDog' is still Fluffy.
// Upon calling the 'handle' method, a reference to my dog named Fluffy is
// copied to the local reference 'inputDog'. A new dog with the name Jack is
// constructed and stored into the 'inputDog' variable, which is distinct
// from the 'myDog' variable. So 'myDog' doesn't change at all.