【问题标题】:Unable to add elements to a Collection by passing it by reference to a method无法通过引用方法将元素添加到集合
【发布时间】:2014-05-21 11:06:03
【问题描述】:

为什么当我将 Set 作为参考传递时,我无法向它添加元素。以下是我的代码:

    public static void main(String[] args)
    {
        Set<String> mySet = null;

        populateSet(mySet);

        if(mySet.contains("A")) {//Getting warning variable can only be null here
            System.out.println("Set populated");
        }else{
            System.out.println("Set Not populated");
        }

    }

    private static void populateSet(Set<String> mySet) 
    {
        mySet = new HashSet<String>();      
        mySet.add("A");
        mySet.add("B");
    }

上面的代码我收到了NullPointerException。但是当我创建一个HashSet 对象并将其作为参考传递时,它工作正常

public static void main(String[] args)
    {
        Set<String> mySet = new HashSet<String>();  

        populateSet(mySet);

        if(mySet.contains("A")) {
            System.out.println("Set populated");
        }else{
            System.out.println("Set Not populated");
        }

    }

    private static void populateSet(Set<String> mySet) 
    {

        mySet.add("A");
        mySet.add("B");
    }

这两种方法有什么区别?

【问题讨论】:

    标签: java collections set pass-by-reference hashset


    【解决方案1】:

    Java 使用“按值传递”语义。因此,当您将“mySet”传递给方法时,原始变量引用的副本将传递给该方法。这意味着如果您将方法内的“mySet”变量引用设置为“null”或分配一个新的 HashSet 实例,它不会影响原始变量引用。但是,您对传入变量指向(或引用)的对象所做的修改将是可见的。之所以如此,是因为即使传递了引用的副本,它们都引用了同一个对象

    【讨论】:

      【解决方案2】:

      在您的第一个示例中,您将空值传递给您的方法。在方法中,此值与 main 方法中的 mySet 变量无关。如果您更改 mySet 参数的值,它只会在此方法的范围内更改它。因此,当您构造一个新的 Set 并将其分配给您的 mySet 参数时,您的 main 方法中没有任何更改。

      您的第二个示例有效,因为您已经构建了Set。这意味着您可以将引用(值)传递给您的 populateSet 方法并愉快地操作它。

      【讨论】:

      【解决方案3】:

      你有一个范围界定问题。

      这里的问题是,您将引用的“null”传递给 populateSet 方法。 覆盖 populateSet 中可用的引用不会影响您传递给 populateSet 的引用。这意味着 mySet 保持为 null 并且您创建的新 HashSet 会丢失。

      这应该可行:

      public static Set<String> mySet = null;
      public static void main(String[] args)
      {
          populateSet();
      
          if(mySet.contains("A")) {//Getting warning variable can only be null here
              System.out.println("Set populated");
          }else{
              System.out.println("Set Not populated");
          }
      
      }
      
      private static void populateSet() 
      {
          mySet = new HashSet<String>();      
          mySet.add("A");
          mySet.add("B");
      }
      

      如果您不想静态声明 mySet,您可以这样做:

      public static void main(String[] args)
      {
          Set<String> mySet = populateSet();
      
          if(mySet.contains("A")) {//Getting warning variable can only be null here
              System.out.println("Set populated");
          }else{
              System.out.println("Set Not populated");
          }
      
      }
      
      private static Set<String> populateSet() 
      {
          mySet = new HashSet<String>();      
          mySet.add("A");
          mySet.add("B");
          return mySet;
      }
      

      编辑:忘记了你的最后一个问题。 如果你将一些参数传递给一个方法,然后在这个方法内部覆盖这个参数,你只会覆盖方法本地引用。调用者已知的引用不会被更改。

      【讨论】:

        猜你喜欢
        • 2015-03-26
        • 1970-01-01
        • 2012-11-08
        • 1970-01-01
        • 2018-01-21
        • 1970-01-01
        • 2020-06-07
        • 2010-09-15
        • 2019-06-16
        相关资源
        最近更新 更多