我写这篇博的原因:
首先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对象
}