0

Why I am unable to add elements to the Set when I am passing it as a reference. Following is my code:

    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");
    }

I am getting NullPointerException for the above code. But when I am creating an HashSet object and passing it as reference, it's working fine

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");
    }

What is the difference between these two approach?

Duncan Jones
  • 67,400
  • 29
  • 193
  • 254
Zeeshan
  • 11,851
  • 21
  • 73
  • 98

3 Answers3

4

Java uses 'pass by value' semantics. So when you pass 'mySet' to the method copy of the original variable reference is passed to the method. This means if you set 'mySet' variable reference inside the method to 'null' or assign a new HashSet instance it wont affect the original variable reference. However the modifications you do to the object which the passed in variable points to (or references), will be visible. This is so because even if a copy of the reference is passed both reference the same object

Dev Blanked
  • 8,555
  • 3
  • 26
  • 32
2

In your first example you pass a null value to your method. Within the method, this value has no relation to your mySet variable in your main method. If you change the value of your mySet argument, it simply changes it within the scope of this method. So when you construct a new Set and assign it to your mySet argument, you've changed nothing in your main method.

Your second example works because you've already constructed the Set. This means that you can pass a reference (value) into your populateSet method and manipulate it happily.

Duncan Jones
  • 67,400
  • 29
  • 193
  • 254
  • hmmmmm.. So Java doesn't have pass-by-reference, It passes reference by value – Zeeshan May 21 '14 at 11:22
  • 1
    @Shaan Exactly, see [Is Java “pass-by-reference” or “pass-by-value”?](http://stackoverflow.com/questions/40480/is-java-pass-by-reference-or-pass-by-value) – Duncan Jones May 21 '14 at 11:22
1

You have a scoping problem there.

The problem here is, that you pass the referenced "null" to the populateSet method. Overwriting the reference available within populateSet doesn't affect the reference you passed to populateSet. This means mySet stays null and the new HashSet you created gets lost.

This should work:

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");
}

If you don't want to declare mySet statically you could do this:

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;
}

Edit: Forgot your last question. If you pass some argument to a method and then overwrite this argument inside of this method you will only overwrite the method-local reference. The reference known to the caller will not be altered.