tags:

views:

329

answers:

5

What are the dos and don'ts while using references in Java?

A: 

Do you mean this? http://www.ibm.com/developerworks/library/j-refs/

Konamiman
+2  A: 

If you mean the SoftReference, WeakReference and PhantomReferences:

Dos:

  • Use soft references to cache objects that are expensive in creation or memory wise. This will give your application a chance to remove objects before running out of memory, at the cost of a performance decrease.

  • Use WeakReferences when using the Observer pattern if you need to hold a reference to the class where you register your Observer. That guarantees that the listener won't prevent the parent from being garbage collected.

Don'ts:

Soft and weak referenced objects can be removed at any time, so never do:

if (reference.get() != null){
  Object o = reference.get();
  // Do something with o....
}

It might be the case that o receives a null pointer, as there is no guarantee when the garbage collector will be actived.

Mario Ortegón
+1  A: 

In short...

Java manipulates objects by reference, and all object variables are references. However, Java doesn't pass method arguments by reference; it passes them by value.

So Objects can be passed into a method by referece, but primitives (int/boolean) are passed by value.

This site does a good job of explaining the differnces... Javaworld: pass by reference

jeff porter
+9  A: 

The common problems that people who are new to Java have with understanding references are:

  • Confusion about Java's parameter passing mechanism. They think that because objects are references, that they are "passed by reference" in a method call. This is not true. Parameters are always "passed by value" in Java.

  • Confusion about what Java arrays are. Arrays are just a special kind of object. They are created on the heap, have references and those references are "passed by value" ... just like any other object.

  • Confusion about what == means for references. It means "is the same object as", not "is equal to". The equals method is for testing if two objects are equal ... whatever that means.

  • A well-known subcase that new users frequently get wrong is when dealing with Strings, where it is common for two String objects to be "equal" but not "the same object". The simple rule is don't use == to compare strings.

  • A less well-known subcase is with the primitive wrapper classes Boolean, Character, Integer and so on. The problem ... and solution ... is essentially the same as for strings; i.e. don't use == to compare instances of Boolean, Character, Integer and so on.

  • Some people have problems with null. The basic concept is simple, but some people get into the bad habit of returning null when they should be throwing exceptions. And this leads to lots of unnecessary testing for null and flakiness due to unanticipated NullPointerExceptions when a necessary null test is left out.

  • Some people think you should be able to create a reference for some object allocated on the stack. Java does not allow this. In Java, objects are always allocated in the heap. The stack frame contains only references and primitive values, and Java does not provide a way to "take the address of" anything.

  • Some people think you should be able to do pointer arithmetic with references. Java does not allow this.

But basically, Java references are really simple and easy to understand, and largely trouble free ... once you stop trying to think about them in terms of C / C++ pointers.

Stephen C
Stephen, an excellent answer, but a question: what are you referring to here by creating a reference to an object created on the stack? My understanding of Java stack variables is that they're essentially like those of C, C++, etc: that's where your local variables get created. And certainly, I can create a reference to one of those, even return it to caller, or assign it to something in a wider scope. So I don't understand what you're (ahem) referring to here. Can you explain?
CPerkins
@Stephen C: I still am confused about Java's parameter passing, I always though If I pass huge array/arraylist to a function only the reference is passed, and the function can now modify the original array. Does it work this way?
Kevin Boyd
@CPerkins: you cannot create a reference to a local variable in Java. You can _copy_ the value of a local variable (which may be of reference type, and therefore the value will be a reference) and return it, but it's not the same thing. In C++, you can create an object directly on the stack and have a pointer/reference to it - not in Java.
Pavel Minaev
A: 

Most of the books, and article and even your test programs in this area may give you bad understanding something like (primitive types are always passed by value, and Objects and Arrays Always passed by reference) and if you tried this using basic test code like the following

 public class Test  {    
        public void changeArrayValues(String[] names) {
            for(int i=0; i<names.length; i++)
                names[i] += "_ALTERED";
        }

        public static void main(String[] args) {
            String[] names = {"Cairo", "Alex", "Giza"};
            for(int i=0; i<names.length; i++)
                System.out.print(names[i] + ", ");
            System.out.println();
            new Test().changeArrayValues(names);
            for(int i=0; i<names.length; i++)
                System.out.print(names[i] + ", ");
        }
    }

you will get the following output:

Cairo, Alex, Giza, Cairo_ALTERED,

Alex_ALTERED, Giza_ALTERED

which will enforce the idea into your head.

but (primitive types are always passed by value, and Objects and Arrays Always passed by reference) is in correct. because in pass by reference you can move the reference to point to another object but in Java if you did this the referenced object will not feel with that change

try this

public class Test  {    

    public void reIntializeArray(String[] names) {
        names = new String[]{"X", "Y", "Z"};
    }

    public static void main(String[] args) {
        String[] names = {"Cairo", "Alex", "Giza"};
        for(int i=0; i<names.length; i++)
            System.out.print(names[i] + ", ");
        System.out.println();
        new Test().reIntializeArray(names);
        for(int i=0; i<names.length; i++)
            System.out.print(names[i] + ", ");
    }
}

and this will dump the following output:

Cairo, Alex, Giza,

Cairo, Alex, Giza,

so the array didn't get initialized with the new values as you see from the output.

so all pass in Java are pass by values

however you can benefit from the - first behavior - in altering the object content but you have to keep in mind that this is Java and not C++.

Ali Abdel-Aziz