1

Just getting my feet wet with Java so I apologize if this seems a bit naive. I'm trying to get a better understanding of the conventions for accessing instance / member variables in practice.

Can a non-static instance variable be manipulated from a non-static context?

For instance, How could one modify the following class definition to allow the id and version variables to increment.

    class Foo {
    
        private int id;
        private int version;
        public String product;
        public String model;
    
        private Foo( ) {
    
            // Can these variables be accessed from a non-static context?
            id++;
            version++;
    
        }
        ...

In comparison with static fields ...

      class Foo {

        private static int id;
        private static int version;
        public String product;
        public String model;

        private Foo( ) {

            id++;
            version++;

        }
        ...

        

First Example ...

1
1
Model One
First

1
1
Model Two
Second

Second Example ...

1
1
Model One
First

2
2
Model Two
Second

4
  • 2
    So all that code is the minimum required to demonstrate your question? I didn't think so... it's copy-paste laziness. Please read SSCCE Commented Nov 14, 2012 at 19:30
  • @Bohemian I wasn't intending to be lazy I simply wanted to provide a clear example of what I intended to express. Sorry if it was overly verbose. Commented Nov 14, 2012 at 19:35
  • @Bohemian ... Updated ... Better? Commented Nov 14, 2012 at 19:53
  • 1
    Much better! Much clearer now. Commented Nov 14, 2012 at 20:56

5 Answers 5

3

You can access a static-variable from a non-static context, because static variables are bound to a class. So, even if you access it within a non-static context, it is accessed just like in static context.

For e.g: -

MyClass obj = null;
obj.staticVar = 10;

Surprisingly the above code does not throw NPE, as the static varible is accessed on class name regardless of how you are accessing it.

So, obj.staticVar is actually replaced with MyClass.staticVar.

But the reverse is not true. You cannot access a non-static variable from a static context. Because, in a static context, you don't have any reference to an instance. And you can't access instance variable without any reference to an instance of that class.


Having said that, also note that, just because you can do something, doesn't mean that it is a good idea. Modifying a static variable inside a constructor or in any non-static context is a terrible idea. Because, any change you make to those variables, will be reflected for all the instances of that class.

Rather, you should use a static-initialization block to initialize the static variables. Static initialization block is executed at class-loading time, to initialize all the static variables.

Sign up to request clarification or add additional context in comments.

1 Comment

+1 Thanks for the should disclaimer ... I'm trying to apply my understanding of the rules of architectural blueprints which state, "Should" means you can; "Shall" means you must.
2

Static fields are shared across instances.

On the contrary, instances fields are closed to one specific instance scope.

That's explain why your fields seem "reset" when you get them from a second instance.

So, to increment your first instance's fields, provide some public methods like this one:

public void incrementId(){
  id++;
}

So that you can achieve your requirement with:

fooOne.incrementId(); // id => 2

fooTwo.incrementId(); // id => 2

5 Comments

+1 I like your perspective here ... In this respect could I simply have an abstract class to provide the default ctor fields for all the instances?
@Eddie B Abstract class will not change the concept. Even if this one contains the instance's fields, they would be closed strictly to their instance scope 'cause abstract class + subclass are "merged" to create one instance. If you really need to share those fields across every instance, make them static.
@Eddie B I advise you to check for this perfect book: amazon.com/SCJP-Certified-Programmer-Java-310-065/dp/0071591060 The best I've read to learn basic Java concepts.
Ordering now ... You rock :-)
@Eddie B It's really focus on Java 6, but Java 7 doesn't bring a lot of things at all and by the way the new book doesn't exist yet. You're welcome ;)
2

If you're trying to mantain those attributes as static variables in the class I'd highly discourage you to do so. Those id and version fields should go in a particular class that manages them, for that object and for every object that would need them.

That way, you can ask your "IdManager" for a new id and a new version and assign those to the object you created.

Just to answer your question, a static field is shared through all the instances of a certain class` so any modification impacts all of the instances.

1 Comment

Thanks for the answer ... I understood that static variables are 'Global' to the class I was quite sure if they could be (or should be) manipulated from an instance of the class. I wouldn't think it to be very wise to do so ...
1

What you demonstrated is in fact the desired behaviour.

In your first example you declare instance variables and increment them in the constructor, which only affects the instance.

In your second example you declare static/class variables and increment them in the constructor. As you instantiate the class two times and each constructor invocation increments the class variables, thus incrementing them twice.

1 Comment

@Bhesh: Thanks for correcting my mistakes. I thought your way and wrote it the wrong way ;)
0

I think what you really want is something like this

    private static int globalID;
    private int id;
    private static int version;
    public String product;
    public String model;

    private Foo( ) {

        this.id = globalID;
        globalID++;
        //...
      }

1 Comment

Except that you'd want to use an AtomicInteger and either incrementAndGet() or getAndIncrement() to manage the concurrency.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.