4

I am having problems understanding the way non-static variables are handled. I chose to work with an array so that it is easy to retrieve its memory address.

Consider the following code:

public class tryClass
{
    int[] v = {0}; // vector v is non-static (and NOT local to any method)
    tryClass obj;
    public void met ()
    {
        obj = new tryClass();
        obj.v[0] = 30;
        v[0]=3;
    }
    public static void main (String[] args)
    {
        tryClass obj = new tryClass(); // is this the SAME object as in met() ?
        int[] v = new int[1];
        obj.v[0] = 40;
        obj.met();
    }
}

In order to know at each step how vector v is handled I filled the code with some println instructions and my ouput is as follows:

In main(), BEFORE running met()
    obj.v[0] = 40
    obj.v    = [I@78456a0c

INSIDE method met()
    obj.v[0] = 30
    v[0]     = 3
    obj.v    = [I@15357784
    v        = [I@78456a0c

In main(), AFTER running met()
    obj.v[0] = 3
    obj.v    = [I@78456a0c

I am very puzzled by many things, the first of which is why the reference of obj.v when called in static method main() is the same as that of v inside non-static method met(). Besides, what exactly is v when called with no object (in a non-static context, of course)?

I am new to Java and I really have an infinity of questions, I hope an answer can solve them altogether... Thanks in advance for your help.

For the sake of completeness, the full code is

public class tryClass
{
    int[] v = {0};
    tryClass obj;
    public void met ()
    {
        obj = new tryClass();
        obj.v[0] = 30;
        v[0]=3;
        System.out.println("\nINSIDE method met()");
        System.out.println("\tobj.v[0] = "+obj.v[0]);
        System.out.println("\tv[0]     = "+v[0]);
        System.out.println("\tobj.v    = "+obj.v);
        System.out.println("\tv        = "+v);
    }
    public static void main (String[] args)
    {
        tryClass obj = new tryClass();
        int[] v = new int[1];
        obj.v[0] = 40;
        System.out.println("In main(), BEFORE running met()");
        System.out.println("\tobj.v[0] = "+obj.v[0]);
        System.out.println("\tobj.v    = "+obj.v);
        obj.met();
        System.out.println("\nIn main(), AFTER running met()");
        System.out.println("\tobj.v[0] = "+obj.v[0]);
        System.out.println("\tobj.v    = "+obj.v);
    }
}
James Dunn
  • 8,064
  • 13
  • 53
  • 87
AndreasT
  • 207
  • 2
  • 8
  • 1
    You have created instanceof tryClass. So no matter whether you print in Main or class methods, you are printing the "array" references from that "instance" obj and hence same reference – Optional Oct 03 '13 at 14:56
  • Read about static methods and classes, as well as how field scope works when using static and instance fields. Here's a hint: try putting your (static) "main" method in a separate class (called Start or something), and leave your "tryClass" free of it. This way it may look clearer why a (static) method-local field has nothing to do with a (non-static) instance field: http://docs.oracle.com/javase/tutorial/java/javaOO/classvars.html I also think that giving some details as to what other languages you're familiar with might help the people who will answer you. – Shivan Dragon Oct 03 '13 at 14:58
  • 1
    Note that, as @ShivanDragon said, non-static variables are more properly known as instance fields (same applies for methods). – LexLythius Oct 03 '13 at 15:03
  • @ShivanDragon Thank you, I am trying straightaway what you suggested. Anyway, I am not very into programming languages and Java is the only OOP I "know". I just have a "fair" knowledge of Unix's Bash programming, but I don't think that is going to be of any help, is it? – AndreasT Oct 03 '13 at 15:05

3 Answers3

1

Why is the reference of obj.v, when called in static method main() the same as that of v inside non-static method met()?

Answer: Because you didn't reassign it to a different object in memory. It's still pointing to the same "array" object in memory, even though you altered the contents of the array internally.

Looking at your code, with my comments:

public class tryClass
{
    // here, non-static variable v will be instantiated
    // as an array with a length of one, holding the value 0 in it's one slot;
    // it will be instantiated when an instance of tryClass is created.
    int[] v = {0};

    // here, this tryClass has another tryClass named "obj" in it as one of its fields.
    tryClass obj;

    public void met ()
    {
        // here, the tryClass's tryClass obj is instantiated
        // and this second tryClass's "v" is instantiated
        // and then it's one slot is set to 30.
        obj = new tryClass();
        obj.v[0] = 30;

        // now, the first tryClass's "v" is set to 3.
        v[0]=3;
    }

    public static void main (String[] args)
    {
        // creating a new tryClass.  This is NOT the same object as in met.
        // But it CONTAINS the same object in met.
        // You could call it by going obj.obj.
        tryClass obj = new tryClass(); // is this the SAME object as in met() ?  Answer: No.

        // this does nothing, it just creates another int[] v
        // that exists only inside the main() method.  It is not
        // the same as obj.v!
        int[] v = new int[1];

        // changing the contents of obj.v, but not reassigning obj.v itself.
        obj.v[0] = 40;

        // calling met, which will change obj.v's contents again, but not reassign it.
        obj.met();
    }
}

Arrays are mutable, meaning that even though it remains the same object in memory, it's contents can be altered.

James Dunn
  • 8,064
  • 13
  • 53
  • 87
  • Thank you very much, your step by step guide is really appreciated. But what do you mean when you say `// here, this tryClass has another tryClass named "obj" in it as one of its fields.`? – AndreasT Oct 03 '13 at 15:34
  • I think I'm getting it now: I created two objects `obj`, the first in the `main()` method, and the second in `met()`. Calling `obj.met()` causes the second `obj` to be a kind of "sub-object" of the first, to which I am supposed to access through `obj.obj`. Did I get you right, and is the order 'first `obj` and second `obj`' correct? – AndreasT Oct 03 '13 at 15:42
  • @AndreasT Yes, that's correct, and I think you're understanding it. "sub-object" is one way to think of it, but in object-oriented programming, think of it in terms of HAS-A. tryClass HAS-A tryClass. – James Dunn Oct 03 '13 at 15:54
1

You should also print out the obj reference's value, and when not in a static context, the value of this too. That would reveal, that you are printing the values of the v references for different instances of the tryClass class...

public class tryClass
{
    int[] v = {0};
    tryClass obj;
    public void met ()
    {
        obj = new tryClass();
        obj.v[0] = 30;
        v[0]=3;
        System.out.println("\nINSIDE method met()");
        System.out.println("\tthis     = "+this); //add this
        System.out.println("\tobj      = "+obj);  //add this
        System.out.println("\tobj.v[0] = "+obj.v[0]);
        System.out.println("\tv[0]     = "+v[0]);
        System.out.println("\tobj.v    = "+obj.v);
        System.out.println("\tv        = "+v);
    }
    public static void main (String[] args)
    {
        tryClass obj = new tryClass();
        int[] v = new int[1];
        obj.v[0] = 40;
        System.out.println("In main(), BEFORE running met()");
        System.out.println("\tobj      = "+obj); //and this
        System.out.println("\tobj.v[0] = "+obj.v[0]);
        System.out.println("\tobj.v    = "+obj.v);
        obj.met();
        System.out.println("\nIn main(), AFTER running met()");
        System.out.println("\tobj      = "+obj); //and also this
        System.out.println("\tobj.v[0] = "+obj.v[0]);
        System.out.println("\tobj.v    = "+obj.v);
    }
}

You could also create a constructor for the class too:

public tryClass() {
    System.out.println("Creating new instance of tryClass!");
}

to see what is going on...

(Or alternatively, as a learning experience, you could check out the debugger in your IDE. That will come in handy a lot...)

ppeterka
  • 20,583
  • 6
  • 63
  • 78
1

When you execute the static main method, the first thing you do is to create an instance of tryClass, and you print the value of one element of the array called v, which is an attribute of that instance. (obj.v[0]). Then you invoke the method met of that instance, so non static references in the body of that method refer to the attributes of that instance ( the one you created on main method).

user1093643
  • 251
  • 1
  • 3
  • 13