我需要明确释放Graphics对象吗?

6

Java 文档中提到:

为了提高效率,程序员只有在使用 Graphics 对象时,如果该对象直接从一个组件或另一个 Graphics 对象创建而来时,才应该在使用完后调用 dispose 方法。

那么在下面的代码中,在返回之前我是否需要调用 graphics.dispose() 方法呢?或者说我可以不调用吗?

{  ...  
BufferedImage result = new BufferedImage(toWidth, toHeight, BufferedImage.TYPE_INT_RGB);  

java.awt.Graphics graphics=result.getGraphics();

graphics.drawImage(im.getScaledInstance(toWidth, toHeight, java.awt.Image.SCALE_SMOOTH), 0, 0, null);  

return result;  
}

返回BufferedImage result,并在其他地方使用。


由于“result”及其相关的图形对象(“graphics”)在方法调用后超出范围,我会说是的。 - Binkan Salaryman
Java通过引用返回对象。因此,如果他处理了图形对象,他能否再次使用它来返回对象?我不知道,也许有人可以回答这个问题。 - Loki
@Loki 如果他处理掉它,就不能再使用了。 - Kayaman
1
@Loki 不应该保留 Graphics 对象,如果需要重复使用,应该从 BufferedImage 中重新获取。请注意及时释放资源。 - Kayaman
@Kayaman,是的,我刚意识到这一点,并发布了一个小例子来展示这种行为。 - Loki
显示剩余3条评论
3个回答

7

Graphics对象可以被释放,也应该被释放。

BufferedImagegetGraphics调用在内部委托给createGraphics,因此没有区别。最终,createGraphics调用会委托给相应的GraphicsEnvironment实现,在SunGraphicsEnvironment中创建一个SunGraphics2Dnew实例。

最后,SunGraphics2Ddispose方法如下所示:

  /**
   * This object has no resources to dispose of per se, but the
   * doc comments for the base method in java.awt.Graphics imply
   * that this object will not be useable after it is disposed.
   * So, we sabotage the object to prevent further use to prevent
   * developers from relying on behavior that may not work on
   * other, less forgiving, VMs that really need to dispose of
   * resources.
   */
  public void dispose() {
      surfaceData = NullSurfaceData.theInstance;
      invalidatePipe();
  }

这也说明了为什么即使在默认实现中没有必要,dispose 确实应该被调用。


1
public class Main{

    public static void main(String[] args) {
        BufferedImage img = get();

        Graphics g = img.getGraphics();

        //g.drawOval(5, 5, 5, 5); //this statement will work (you'll see the cirle)

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
            ImageIO.write( img, "jpg", baos );

            baos.flush();
            byte[] imageInByte = baos.toByteArray();
            baos.close();

            Files.write(Paths.get("test2.png"), imageInByte);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }


    public static BufferedImage get(){
        BufferedImage res = new BufferedImage(50, 50, BufferedImage.TYPE_INT_ARGB);

        Graphics g = res.getGraphics();

        g.drawRect(0, 0, 20, 20);

        g.dispose();

        g.drawOval(5, 5, 5, 5); //this statement won't work, you'll only see the rect

        return res;
    }


}

如您所见,您可以安全(并且应该)在您的方法中释放graphics

您不能在方法中再次使用该图形对象,因此当您运行代码时,图片中不会有圆形。但是,如果您在方法中注释掉g.drawOval(5,5,5,5),但在main方法中取消相同语句的注释,则会看到一个圆形。因此您可以在之后使用它。


0
由于JavaDoc中getGpahics()方法转发到createGraphics(),因此您应该在方法末尾处处理Graphics对象。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接