Java调用PrintJob的getGraphics方法出现ClassCastException异常
异常产生原因
- 报错本质是类型强转不匹配:
sun.print.ProxyPrintGraphics直接继承自java.awt.Graphics,没有继承java.awt.Graphics2D,而Swing组件(包括你代码里的JPanel)的内部绘制逻辑从JDK1.2版本开始就默认基于Graphics2D实现,调用print(Graphics g)方法时会在内部直接把传入的Graphics对象强转为Graphics2D来配置渲染参数、执行绘制操作,传入不符合类型要求的ProxyPrintGraphics时就会触发ClassCastException。 - 你使用的
Toolkit.getPrintJob()是JDK1.0时期遗留的AWT原生打印接口,这套接口设计时还没有Graphics2D类,高版本JDK(9及以上模块化版本)中这套接口返回的ProxyPrintGraphics实例没有做Swing兼容适配,无法直接传给Swing组件的打印/绘制方法。
修复方案
直接废弃老的AWT PrintJob接口,改用JDK标准的java.awt.print.PrinterJob打印API,这套API的打印上下文固定返回Graphics2D类型实例,完全兼容Swing组件的渲染逻辑,是官方推荐的Java打印实现方式。
修正后的可运行代码如下:
try { PrinterJob printerJob = PrinterJob.getPrinterJob(); // 定义打印内容规则 printerJob.setPrintable(new Printable() { @Override public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException { // 仅处理第一页打印,超出页码范围直接返回无该页 if (pageIndex > 0) { return Printable.NO_SUCH_PAGE; } Graphics2D g2d = (Graphics2D) graphics; // 坐标偏移适配打印页的可打印区域,避免内容打印到页边距外 g2d.translate(pageFormat.getImageableX(), pageFormat.getImageableY()); // 可选:缩放组件尺寸适配打印页宽高,不需要可删除下面两行缩放代码 double scaleRatioX = pageFormat.getImageableWidth() / jPanel3.getWidth(); double scaleRatioY = pageFormat.getImageableHeight() / jPanel3.getHeight(); g2d.scale(scaleRatioX, scaleRatioY); // 执行组件打印,不会再触发类型转换异常 jPanel3.print(g2d); return Printable.PAGE_EXISTS; } }); // 弹出系统打印选择对话框,用户确认后启动打印 if (printerJob.printDialog()) { printerJob.print(); } } catch (PrinterException e) { e.printStackTrace(); }
注意:不要尝试通过反射、强制类型转换等方式把ProxyPrintGraphics转成Graphics2D,这个类是JDK内部实现类,既没有继承Graphics2D,也没有提供对外的转换方法,强转必然失败。如果强行使用老PrintJob接口,需要自行实现Graphics2D的适配层包装ProxyPrintGraphics,实现成本高、跨版本兼容性差,不推荐使用。
内容的提问来源于stack exchange,提问作者itsdicky
相关产品推荐
相关产品推荐

