Dominic Sore
Dominic Sore

Reputation: 385

If I call a static method, does the constructor run

I have a class called Tile with a static method public static BufferedImage grass() and inside the class is also a constructor public Tile() which sets a variable.

So what I'm wondering is if I call the grass() method from another class Tile.grass(), will the constructor run?

I'm assuming not as my grass() method is returning null.

Here is my code:

import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;

public class Tile {

    public static final int size = 50;

    private static BufferedImage mapSprites;

    public Tile(){
        try{
            Tile.setMapSprites(ImageIO.read(getClass().getResource("res/mas.png")));
        } catch (IOException e){
            e.printStackTrace();
        }
    }

    public static BufferedImage grass(){
        return getMapSprites().getSubimage(0, 0, 10, 10);;
    }

    private static BufferedImage getMapSprites() {
        return mapSprites;
    }

    private static void setMapSprites(BufferedImage mapSprites) {
        Tile.mapSprites = mapSprites;
    }
}

I could create a function the gets the mapSprite for every tile I return. But I don't think that would be very efficient. Is there another solution?

(Just for reference here is how I am calling it in my Map class)

public void render(){
    g.drawImage(Tile.grass(), 0, 0, null);
}

Upvotes: 8

Views: 13618

Answers (3)

Paul
Paul

Reputation: 3058

No. It won't. The constructor will execute the first time (and every time) something creates a new instance of Tile.

If you have some code you want to run once, when the class (not the instance) is initialize, you can put it in a static block:

private static BufferedImage mapSprites;
static {
    try{
        Tile.setMapSprites(ImageIO.read(getClass().getResource("res/mas.png")));
    } catch (IOException e){
        e.printStackTrace();
    }
}

An alternative would be to make your class a Singleton.

Upvotes: 3

rgettman
rgettman

Reputation: 178263

No, the constructor doesn't run if you only call a static method of a class. There is no instance of a class associated with a call to a static method. That is why mapSprites is null.

To populate mapSprites, you can move the code that initializes it out of the constructor and into a static initializer. This way, it will run the first time the class is referenced, so that mapSprites is initialized properly when you call a static method for the first time.

static {
    try{
        Tile.setMapSprites(ImageIO.read(Tile.class.getResource("res/mas.png")));
    } catch (IOException e){
        e.printStackTrace();
    }
}

With static initializers, you must be careful to avoid having any exception propagate out of it. If it does, then it will be wrapped in an ExceptionInInitializerError that will be throw and that will be bad news for your program.

You may also want to make the (now useless) constructor private, to prevent instantiation of the class, because your class is now a utility class, where everything is static, and an instance of this class is now useless.

Upvotes: 21

Clashsoft
Clashsoft

Reputation: 11882

You can put the image initialization code inside a static initializer block, because it is shared between all Tile instances.

static {
    try {
        Tile.setMapSprites(ImageIO.read(Tile.class.getResource("res/mas.png")));
    } catch (IOException e){
        e.printStackTrace();
    }
}

That way you don't have to load the image every time you create a new Tile instance.

Concerning your original question, the constructor will only be called if you explicitly use the new operator, as in new Tile().

Upvotes: 0

Related Questions