graphics2D中抽象方法graphics2D.drawString()的實現
阿新 • • 發佈:2018-11-05
我寫這篇博的原因:
首先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物件
}