Reputation: 385
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
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
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
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