【问题标题】:Should I explicitly dispose the Graphics object?我应该明确处置 Graphics 对象吗?
【发布时间】:2015-03-26 08:46:24
【问题描述】:

javadoc 说:

为了提高效率,程序员在使用完一个 图形对象仅当它是直接从组件创建的或 另一个 Graphics 对象。

那么在下面的代码中,我应该在返回之前调用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) 在方法调用后超出范围,我会说是的。
  • Java 通过引用返回对象。那么如果他处置了图形对象,他是否可以再次将其用于返回的对象?我不知道,也许有人可以回答这个问题。
  • @Loki 如果他把它扔掉,他就不能再使用它了。
  • @Kayaman,所以他不应该在这个方法中处理它,因为他返回了 BufferedImage 并且可能想在以后使用它。对吗?
  • 在这个方法中处理它,然后在返回的结果上再次调用getGraphics()的结果是什么?

标签: java swing awt


【解决方案1】:

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确实应该被调用的一个理由(即使它在默认实现中不是绝对必要的)

【讨论】:

    【解决方案2】:
    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-方法中注释相同的语句,你会看到一个圆圈。所以你以后可以使用它。

    【讨论】:

      【解决方案3】:

      由于 JavaDoc getGpahics() 方法转发到 createGraphics(),您应该在方法结束时释放 Graphics 对象。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-05-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-12-17
        • 1970-01-01
        • 2015-01-06
        • 2018-03-06
        相关资源
        最近更新 更多