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对象
    }

猜你喜欢

转载自blog.csdn.net/weixin_39841821/article/details/82222584
今日推荐