tags:

views:

853

answers:

6

I'm trying to work this out.

In my project, i have a file called 'Hello.java' which is the file with the main() argument and which is called when the program is compiled. And I have another file called MyObj.java which has got just a random class I made up to test java's OO features. I'm trying to do this:

class Hello
{
    public MyObj an_obj;
    public static void main(String[] args)
    { 
        setObj();
    }       

    public void setObj()
    {
        this.an_obj.set_size(7);
        say("size is " + this.an_obj.get_size());
    }    
}

In the MyObj.java class i have this code:

public class MyObj
{
    private int size;

    public MyObj()
    {
        //do nothing
    }

    public void set_size(int new_size)
    {
        this.size=new_size;
    }

    public int get_size()
    {
        return this.size;
    }   
}

This however gives the error:

"Cannot make a static reference to non-static method setObj() from the type Hello".

If I add 'static' to the declaration of setObj, i.e

public static void setObj()

Then I get:

Cannot make a static reference to non-static field an_obj.

My question is, how can I accomplish what I'm doing, i.e setting and retreiving an object's field if the only way to start a program is with the Main method, and the main Method can only call static methods?? In what, how can I do anything at all with this limitation of being able to call static methods only?????

+12  A: 

You can either add "static" to the member variable as well, or instantiate the class from within your main method. Here is some example code for both approaches:

/* Static */
class Hello {
    public static MyObj an_obj;
    public static void main(String[] args) { 
        setObj();
    }           

    public static void setObj() {
        this.an_obj.set_size(7);
        say("size is " + this.an_obj.get_size());
    }
}

/* Non-Static */
class Hello {
    public MyObj an_obj;
    public static void main(String[] args) {
        Hello hello = new Hello(); 
        hello.setObj();
    }           

    public void setObj() {
        this.an_obj.set_size(7);
        say("size is " + this.an_obj.get_size());
    }
}

The primary difference between these two approaches is that in the first, "an_obj" is static--that is to say, there is only one variable for the entire program. If you were to instantiate multiple Hello objects, they would all have the same "an obj" reference. In the second, each Hello object has its own "an obj" reference, each of which can point to a different MyObj instance.

Obviously in this simple situation it doesn't make any difference one way or the other, but generally speaking, static members and methods should be avoided when possible.

Ross
Bah, just beat me. +1
Zach Langley
I added some code too, following your example. Hopefully that will get another few pluses. :)
Ross
If I added some more code to the class, such as the ability to internally change its variable's values etc, would the 'static' keyword continue to work or will it prevent it from doing so?
Click Upvote
It will continue to prevent it from doing so, unless you make all the data and methods that operate on that data static, which is the wrong approach. You normally would want to do the second non-static example and create a new Hello object on which to operate.
mtruesdell
@Ross, that addition definitely seems to have helped!
Zach Langley
@Java, every method that is static can only reference or modify variables that are static. A method that is not static can modify both static and non-static variables, but such a method can only be called if you have an instantiated object.
Ross
+8  A: 

Make both the setObj() method and the an_obj variable static, or do something like:

public static void main(String[] args) {
    new Hello().setObj();
}
Zach Langley
+2  A: 

You never created an instance of MyObj.

There are two logical places to create the necessary object.

  1. Hello's initialization.

    public MyObj an_obj= new MyObj();
    public static void main(String[] args)
    { 
        setObj();
    }
    
  2. Inside main()

    public MyObj an_obj;
    public static void main(String[] args)
    { 
        an_obj= new MyObj()
        setObj();
    }
    

Either way, you have to actually create an object.

Additionally, you can make setObj static. However, this is rarely what you intend.

The correct thing is for main to (1) create relevant objects, and (2) turn control over to those objects. This is what you should do.

class Hello
{
    public MyObj an_obj= new MyObj();
    public static void main(String[] args)
    { 
        Hello aHelloObject= new Hello();
        aHelloOject.setObj();
    }       

    public void setObj()
    {
        this.an_obj.set_size(7);
        say("size is " + this.an_obj.get_size());
    }    
}
S.Lott
This is true, but it's not the reason for the error.
Zach Langley
It's the common misunderstanding that leads to the error.
S.Lott
No, that's not the misunderstanding - the problem is trying to use an instance method from a static method. Your fix wouldn't help to resolve that.
Jon Skeet
The problem is failing to create an instance of an object. Which leads to failing to understand what static even means.
S.Lott
No, I don't think that *is* the problem. It's certainly *a* problem, but I don't believe it's the first one to tackle - at least not by creating an instance of MyObj. If your answer had created a new instance of Hello and called setObj on that, it would have been fine.
Jon Skeet
(The problem of an_obj being null could have been tackled *then* - but there's no need to conflate the two issues.)
Jon Skeet
Not conflating. Trying to address root cause. Most folks new to OO fail to create objects. They work directly with classes, not understanding that objects are where the real work happens at run time.
S.Lott
But I think Jon Skeet's point is that your first two examples don't work, because you're still trying to access the non-static setObj()/an_obj from a static context. Which is where you're conflating the two problems.
mtruesdell
Not conflating. Solving exactly one. Ignoring the other. Which is not a good thing. But I'm specifically avoiding conflation by focusing on the root cause and ignoring a problem which is consequential not fundamental.
S.Lott
It's not consequential at all. It *is* fundamental. Put it this way - the an_obj variable could be an int, and he'd have the same problem. Applying your suggested changes would leave *exactly the same error*. How does that help him to understand the problem he's actually asking about?
Jon Skeet
(It's not so bad now it's been edited, admittedly - I've only just seen the edit. I was talking about the original post which is what I was originally commenting on - at that point you weren't addressing the question at all.)
Jon Skeet
The problem he's actually asking about is the *wrong* problem. If he had created his objects correctly, the static issue wouldn't arise. Generally, the "instance of the class which contains main()" problem is easier to understand after the fundamental ("forget to create objects") problem is clear.
S.Lott
I think we'll have to agree to disagree on this. Initializing the variable at the point of declaration wouldn't have clarified the meaning of "static" at all. At the very least it's worth asking the question which has been asked, rather than suggesting a change which wouldn't fix the immediate error
Jon Skeet
My point is this: fixing the "immediate error" is often misleading and unhelpful. I find that there are numerous standard mistakes, many of which are fundamental misconceptions. I prefer to address those fundamental issues which surface as an "immediate error" that's really confusing.
S.Lott
I agree that fixing the "immediate error" is often misleading and unhelpful. However, I disagree with your assessment of what the fundamental error is. I think the fundamental error is a lack of understanding of what the "static" keyword does.
Ross
Possibly. My experience is that confusion over static has a root cause. And the root cause is failing to understand object creation in the first place.
S.Lott
Whereas my experience is that failing to understand static is simply failing to understand static - and that solving a different problem than the one asked without at least saying so doesn't help people get over their immediate problem.
Jon Skeet
+5  A: 

In addition to all previous answers I’d like to mention that only because you don’t understand a concept of a language that doesn’t necessarily constitute a “limitation”.

Bombe
A: 

You can only call an instance method (i.e. a non-static method) when you have an instance of a class.

joel.neely
A: 

From a simple perspective, there are two different things in Java:

  • objects
  • static variables/functions

Objects get created at runtime, when you cause them to be created. Static things (all of them) are always there, and are loaded as needed.

While you can mix and match these in your classes, you have to be careful how you use them. A static thing can call an object, but it must create a version of it first. An object, once created can call any static thing it likes.

We do tend to create classes that are objects AND have a few static bits as well, but you can have all static things in a class if you want, or you can just have all object-based things.

Static stuff is generally frowned upon, because it is essentially global, which opens up more possibilities for weird behavior. Objects with no static bits are best, and are usually thread safe if they are not calling things outside of there own internal data (make 95% of your code simple and safe, then deal with the complicate 5% in some special classes).

Paul.

Paul W Homer