【问题标题】:If I call a static method, does the constructor run如果我调用静态方法,构造函数是否运行
【发布时间】:2015-07-30 06:43:40
【问题描述】:

我有一个名为Tile 的类,它有一个静态方法public static BufferedImage grass(),并且在类内部还有一个构造函数public Tile(),它设置了一个变量。

所以我想知道的是,如果我从另一个类Tile.grass() 调用grass() 方法,构造函数会运行吗?

我假设我的 grass() 方法不是返回 null

这是我的代码:

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;
    }
}

我可以创建一个函数,为我返回的每个图块获取mapSprite。但我认为这不会非常有效。还有其他解决方案吗?

(仅供参考,这是我在Map 课程中的称呼方式)

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

【问题讨论】:

  • 测试一下怎么样?在构造函数中放置一个断点并查看。或者 System.out.println("hello from constructor");
  • 不,不会。它是一个静态方法,它不构造实例。
  • @JBNizet - 唯一正确的答案
  • 对,所以我唯一的解决方案是每次调用 tile 方法时设置 mapSprites?
  • 它被否决了,因为一个简单的愚蠢测试会给你答案。

标签: java constructor static scope static-methods


【解决方案1】:

没有。它不会。构造函数将在第一次(并且每次)时执行创建一个new Tile 实例。

如果你有一些代码你想运行一次,当类(不是 instance) 被初始化,你可以把它放在一个静态块中:

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

另一种方法是将您的班级设为Singleton

【讨论】:

    【解决方案2】:

    不,如果您只调用类的静态方法,则构造函数不会运行。没有与对静态方法的调用关联的类的实例。这就是为什么mapSpritesnull

    要填充mapSprites,您可以将初始化它的代码移出构造函数并移入静态初始化程序。这样,它会在第一次引用该类时运行,以便在您第一次调用static 方法时正确初始化mapSprites

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

    使用静态初始化器,您必须小心避免任何异常传播出去。如果是这样,那么它将被包裹在一个 ExceptionInInitializerError 中,这将被抛出,这对你的程序来说是个坏消息。

    您可能还想创建(现在无用的)构造函数private,以防止类的实例化,因为您的类现在是一个实用程序类,其中所有内容都是static,并且该类的实例现在是没用。

    【讨论】:

    • @Clashsoft 你是对的。我把它改成了Tile.class
    【解决方案3】:

    您可以将图像初始化代码放在static 初始化块中,因为它在所有Tile 实例之间共享。

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

    这样您就不必每次创建新的Tile 实例时都加载图像。

    关于您最初的问题,只有当您明确使用new 运算符时才会调用构造函数,如new Tile()

    【讨论】:

      猜你喜欢
      • 2020-02-15
      • 1970-01-01
      • 2013-01-11
      • 1970-01-01
      • 1970-01-01
      • 2016-08-28
      • 2018-09-25
      • 1970-01-01
      • 2021-11-08
      相关资源
      最近更新 更多