1. 程式人生 > >graphics2D中抽象方法graphics2D.drawString()的實現

graphics2D中抽象方法graphics2D.drawString()的實現

我寫這篇博的原因:
首先Graphics2D是抽象類,裡面大部分方法是抽象方法,但是如graphics2D.drawString("Hello",0,200);進行繪圖不需要自己重寫,直接可用,這是為什麼?

先給出結論

總結:

類的繼承關係
1:Graphics->Graphics2D->SunGraphics2D
2:GraphicsEnvironment->SunGraphicsEnvironment->Win32GraphicsEnvironment

所以整個流程是:
1.獲得本地環境Win32GraphicsEnvironment  GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment
();//WIN32 1.1建立環境過程中使用了反射和賦權 1.1.1 AccessController.doPrivileged(new GetPropertyAction("java.awt.graphicsenv", null))//AccessController是一個許可權控制器,doPrivileged()方法是給外部方法作業系統的許可權 1.1.2 得到的是"sun.awt.Win32GraphicsEnvironment"字串 1.1.3 通過Class.forName(nm);反射載入物件 1.1.4 geCls.newInstance
();例項化 //其中geCls是類物件,gs是例項化物件 2.通過環境獲得繪圖物件SunGraphics2D env.createGraphics(this) 3.強制轉化為Graphics2D物件 (Graphics2D) bufferedImage.getGraphics(); 4.使用SunGraphics2D物件的方法比如 graphics2D.setColor(Color.BLACK); graphics2D.setFont(new Font("宋體",Font.BOLD,14)); graphics2D.drawString("Hello"
,0,200);

以下是程式碼分析

主程式碼(測試程式碼)

功能:實現驗證碼的生成

public class VerifyImage {
    public static void main(String[] args) throws IOException {
        BufferedImage bufferedImage = new BufferedImage(400,400,BufferedImage.TYPE_INT_RGB);
        Graphics2D graphics2D = (Graphics2D) bufferedImage.getGraphics();
        graphics2D.setColor(Color.WHITE);
        graphics2D.fillRect(0,0,400,400);

        graphics2D.setColor(Color.BLACK);
        graphics2D.setFont(new Font("宋體",Font.BOLD,14));
        graphics2D.drawString("Hello",0,200);
        ImageIO.write(bufferedImage, "JPEG", new FileOutputStream("F:/b.jpg"));
        System.out.println(bufferedImage.getClass().getName());
        System.out.println(graphics2D.getClass().getName());
    }
}
其實關鍵是在著一句Graphics2D graphics2D = (Graphics2D) bufferedImage.getGraphics();它生成的不是Graphics2D抽象物件,而是其子類SunGraphics2D物件,這個類是一個實類,繼承於Graphics2D對裡面抽象方法進行了重寫,那麼是怎麼獲得SunGraphics2D例項物件的呢?

#### 這裡通過除錯檢視程式碼執行過程(以下均是原始碼)
VerfyImage類->BufferedImage類

Graphics2D graphics2D = (Graphics2D) bufferedImage.getGraphics();//強制向上轉型SunGraphics2D->Graphics2D,使用實際上是用的SunGraphics2D的例項方法

BufferedImage類->GraphicsEnvironMent類

public java.awt.Graphics getGraphics() {
    return createGraphics();//返回SunGraphics2D物件
}

public Graphics2D createGraphics() {
    GraphicsEnvironment env =
        GraphicsEnvironment.getLocalGraphicsEnvironment();  //得到Win32GraphicsEnvironment類物件
    return env.createGraphics(this);//建立通過環境判斷返回了SunGraphics2D物件
}

Win32GraphicsEnvironment extends SunGraphicsEnvironment
GraphicsEnvironMent類

public static synchronized GraphicsEnvironment getLocalGraphicsEnvironment() {
    if (localEnv == null) {
        localEnv = createGE();
    }

    return localEnv;
}

    private static GraphicsEnvironment createGE() {
        GraphicsEnvironment ge;
        String nm = AccessController.doPrivileged(new GetPropertyAction("java.awt.graphicsenv", null));//獲得了當前的繪畫環境,debug返回nm=sun.awt.Win32GraphicsEnvironment
        try {
//          long t0 = System.currentTimeMillis();
            Class<GraphicsEnvironment> geCls;
            try {
                // First we try if the bootclassloader finds the requested
                // class. This way we can avoid to run in a privileged block.
                geCls = (Class<GraphicsEnvironment>)Class.forName(nm);//通過反射載入類
            } catch (ClassNotFoundException ex) {
                // If the bootclassloader fails, we try again with the
                // application classloader.
                ClassLoader cl = ClassLoader.getSystemClassLoader();
                geCls = (Class<GraphicsEnvironment>)Class.forName(nm, true, cl);
            }
            ge = geCls.newInstance();//例項化Win32GraphicsEnvironment類
//          long t1 = System.currentTimeMillis();
//          System.out.println("GE creation took " + (t1-t0)+ "ms.");
            if (isHeadless()) {
                ge = new HeadlessGraphicsEnvironment(ge);
            }
        } catch (ClassNotFoundException e) {
            throw new Error("Could not find class: "+nm);
        } catch (InstantiationException e) {
            throw new Error("Could not instantiate Graphics Environment: "
                            + nm);
        } catch (IllegalAccessException e) {
            throw new Error ("Could not access Graphics Environment: "
                             + nm);
        }
        return ge;//返回Win32GraphicsEnvironment物件
    }