??xml version="1.0" encoding="utf-8" standalone="yes"?>
This programm loads an image via java.awt.Toolkit
, scales it down to a user-defined resolution and saves it as a JPEG file. The first part, the loading of the original image, is done the same way as in Viewer. So if you don't know yet how loading images with Toolkit
works you might want to study that program first.
Different from Viewer, this program (Thumbnail) works on the command line. So you won't get any windows or other graphical user interface components. The only visual feedback is the word Done.
after the program successfully terminated.
To use this program do the following:
Thumbnail.java
(regard case). Thumbnail.java
is and compile it: javac Thumbnail.javaYou should now have a new class file
Thumbnail.class
.java Thumbnail c:\image.jpg c:\thumbnail.jpg 120 80 75The file
image.jpg
must exist already, thumbnail.jpg
will be created (and any existing file of that name overwritten).You will need Java 1.2 or higher to successfully run this program. The com.sun.image.codec.jpeg
package that will be used for saving the thumbnail is not available with all Java development kits, but as long as you are using a Sun JDK, it should be present.
With Java 1.4 a new way of writing JPEG files was introduced, the image I/O library in the package javax.imageio
. See the Screenshot.java example program. It saves as PNG, but all you have to do is change the second argument of ImageIO.write
from png
to jpg
. The advantage of ImageIO
: It is available with each 1.4+ JDK and JRE, not only those coming from Sun.
Now let's see how this program works. First, it is checked that we have exactly five arguments. If this is not the case, an error message is printed to output and the program terminates.
Next, the input image is loaded via Toolkit
and MediaTracker
just as it was done in Viewer.
The third and fourth program argument contain the maximum size of the thumbnail to be created. The actual size of the thumbnail will be computed from that maximum size and the actual size of the image (all sizes are given as pixels). The code that does this is not really very readable, and also not essential to loading and saving image files. But it is necessary to create a thumbnail that is scaled correctly.
As an example, if the two arguments for the maximum thumbnail size are both 100
and the image that was loaded is 400
times 200
pixels large, we want the thumbnail to be 100
times 50
pixels large, not 100
times 100
, because the original image is twice as wide as it is high. A 100
times 100
pixel thumbnail would contain a very skewed version of the original image.
Now that we have determined the size of the thumbnail we create a BufferedImage
of that size, named thumbImage
. We ask for a Graphics2D
object for that new thumbnail image and call its drawImage
method to draw the original image on that new image. The call to drawImage
does the actual scaling. The rendering hints for bilinear interpolation can be left out if quality is not that necessary and speed more important. For nicer results (at least in some cases) try RenderingHints.VALUE_INTERPOLATION_BICUBIC
instead of RenderingHints.VALUE_INTERPOLATION_BILINEAR
.
In order to save the scaled-down image to a JPEG file, we create a buffered FileOutputStream
with the second argument as name and initialize the necessary objects from the com.sun.image.codec.jpeg
package. The quality argument from the command line is converted from the interval 0
to 100
to the interval 0.0f
to 1.0f
, because that's what the codec expects (I mostly use 0.75f
). The higher that quality number is, the better the resulting thumbnail image quality, but also the larger the resulting file.
The call to System.exit(0);
is unfortunately necessary for some Java runtime environments (because of a bug that keeps the AWT thread from terminating).
import com.sun.image.codec.jpeg.*;
import java.awt.*;
import java.awt.image.*;
import java.io.*;
/**
* Thumbnail.java (requires Java 1.2+)
* Load an image, scale it down and save it as a JPEG file.
* @author Marco Schmidt
*/
public class Thumbnail {
public static void main(String[] args) throws Exception {
if (args.length != 5) {
System.err.println("Usage: java Thumbnail INFILE " +
"OUTFILE WIDTH HEIGHT QUALITY");
System.exit(1);
}
// load image from INFILE
Image image = Toolkit.getDefaultToolkit().getImage(args[0]);
MediaTracker mediaTracker = new MediaTracker(new Container());
mediaTracker.addImage(image, 0);
mediaTracker.waitForID(0);
// determine thumbnail size from WIDTH and HEIGHT
int thumbWidth = Integer.parseInt(args[2]);
int thumbHeight = Integer.parseInt(args[3]);
double thumbRatio = (double)thumbWidth / (double)thumbHeight;
int imageWidth = image.getWidth(null);
int imageHeight = image.getHeight(null);
double imageRatio = (double)imageWidth / (double)imageHeight;
if (thumbRatio < imageRatio) {
thumbHeight = (int)(thumbWidth / imageRatio);
} else {
thumbWidth = (int)(thumbHeight * imageRatio);
}
// draw original image to thumbnail image object and
// scale it to the new size on-the-fly
BufferedImage thumbImage = new BufferedImage(thumbWidth,
thumbHeight, BufferedImage.TYPE_INT_RGB);
Graphics2D graphics2D = thumbImage.createGraphics();
graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
graphics2D.drawImage(image, 0, 0, thumbWidth, thumbHeight, null);
// save thumbnail image to OUTFILE
BufferedOutputStream out = new BufferedOutputStream(new
FileOutputStream(args[1]));
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
JPEGEncodeParam param = encoder.
getDefaultJPEGEncodeParam(thumbImage);
int quality = Integer.parseInt(args[4]);
quality = Math.max(0, Math.min(quality, 100));
param.setQuality((float)quality / 100.0f, false);
encoder.setJPEGEncodeParam(param);
encoder.encode(thumbImage);
out.close();
System.out.println("Done.");
System.exit(0);
}
}
q是一程序员写给E序员的味ȝ。所谓趣x指可以比较轻村֜了解一些原来不清楚的概念,增进知识Q类g打RPG游戏的升U。整理这文章的动机是两个问题:
使用WindowsC本的“另存ؓ”,可以在GBK、Unicode、Unicode big endian和UTF-8q几U编码方式间怺转换。同htxt文gQWindows是怎样识别~码方式的呢Q?/P>
我很早前发现Unicode、Unicode big endian和UTF-8~码的txt文g的开头会多出几个字节Q分别是FF、FEQUnicodeQ?FE、FFQUnicode big endianQ?EF、BB、BFQUTF-8Q。但q些标记是基于什么标准呢Q?/P>
查了查相兌料,ȝ这些问题弄清楚了,带也了解了一些Unicode的细节。写成一文章,送给有过cM疑问的朋友。本文在写作时尽量做到通俗易懂Q但要求读者知道什么是字节Q什么是十六q制?/P>
big endian和little endian是CPU处理多字节数的不同方式。例如“汉”字的Unicode~码?C49。那么写到文仉ӞI竟是将6C写在前面Q还是将49写在前面Q如果将6C写在前面Q就是big endian。如果将49写在前面Q就是little endian?/P>
“endian”这个词《格列佛游记》。小人国的内战就源于吃鸡蛋时是究竟从大头(Big-Endian)敲开q是从小?Little-Endian)敲开Q由此曾发生q六ơ叛乱,一个皇帝送了命,另一个丢了王位?/P>
我们一般将endian译成“字节序”,big endian和little endianUC“大䏀和“小䏀?/P>
字符必须~码后才能被计算机处理。计机使用的缺省编码方式就是计机的内码。早期的计算Z?位的ASCII~码Qؓ了处理汉字,E序员设计了用于体中文的GB2312和用于繁体中文的big5?/P>
GB2312(1980q?一共收录了7445个字W,包括6763个汉字和682个其它符受汉字区的内码范围高字节从B0-F7Q低字节从A1-FEQ占用的码位?2*94=6768。其中有5个空位是D7FA-D7FE?/P>
GB2312支持的汉字太?995q的汉字扩展规范GBK1.0收录?1886个符P它分为汉字区和图形符号区。汉字区包括21003个字W?/P>
从ASCII、GB2312到GBKQ这些编码方法是向下兼容的,卛_一个字W在q些Ҏ中L有相同的~码Q后面的标准支持更多的字W。在q些~码中,英文和中文可以统一地处理。区分中文编码的Ҏ是高字节的最高位不ؓ0。按照程序员的称|GB2312、GBK都属于双字节字符?(DBCS)?/P>
2000q的GB18030是取代GBK1.0的正式国家标准。该标准收录?7484个汉字,同时q收录了藏文、蒙文、维向ְ文等主要的少数民族文字。从汉字字汇上说QGB18030在GB13000.1?0902个汉字的基础上增加了CJK扩展A?582个汉字(Unicode?0x3400-0x4db5Q,一共收录了27484个汉字?/P>
CJK是中日韩的意思。UnicodeZ节省码位Q将中日韩三国语a中的文字l一~码。GB13000.1是ISO/IEC 10646-1的中文版Q相当于Unicode 1.1?/P>
GB18030的编码采用单字节、双字节?字节Ҏ。其中单字节、双字节和GBK是完全兼容的?字节~码的码位就是收录了CJK扩展A?582个汉字?例如QUCS?x3400在GB18030中的~码应该?139EF30QUCS?x3401在GB18030中的~码应该?139EF31?/P>
微Y提供了GB18030的升U包Q但q个升包只是提供了一套支持CJK扩展A?582个汉字的新字体:新宋?18030Qƈ不改变内码。Windows 的内码仍然是GBK?/P>
q里q有一些细节:
GB2312的原文还是区位码Q从Z码到内码Q需要在高字节和低字节上分别加上A0?/P>
对于M字符~码Q编码单元的序是由~码Ҏ指定的,与endian无关。例如GBK的编码单元是字节Q用两个字节表示一个汉字?q两个字节的序是固定的Q不受CPU字节序的影响。UTF-16的编码单元是wordQ双字节Q,word之间的顺序是~码Ҏ指定的,word内部的字节排列才会受到endian的媄响。后面还会介lUTF-16?/P>
GB2312 的两个字节的最高位都是1。但W合q个条g的码位只?28*128=16384个。所以GBK和GB18030的低字节最高位都可能不?。不q这不媄响DBCS字符的解析Q在dDBCS字符时Q只要遇到高位ؓ1的字节,可以将下两个字节作Z个双字节~码Q而不用管低字节的高位是什么?/P>
前面提到从ASCII、GB2312、GBK到GB18030的编码方法是向下兼容的。而Unicode只与ASCII兼容Q更准确地说Q是与ISO-8859-1兼容Q,与GB码不兼容。例如“汉”字的Unicode~码?C49Q而GB码是BABA?/P>
Unicode也是一U字W编码方法,不过它是由国际组l设计,可以容纳全世界所有语a文字的编码方案。Unicode的学名是"Universal Multiple-Octet Coded Character Set"Q简UCؓUCS。UCS可以看作?Unicode Character Set"的羃写?/P>
Ҏl基癄全书(http://zh.wikipedia.org/wiki/)的记载:历史上存在两个试囄立设计Unicode的组l,卛_际标准化l织QISOQ和一个Y件制造商的协会(unicode.orgQ。ISO开发了ISO 10646目QUnicode协会开发了Unicode目?/P>
?991q前后,双方都认识到世界不需要两个不兼容的字W集。于是它们开始合q双方的工作成果Qƈ为创立一个单一~码表而协同工作。从Unicode2.0开始,Unicode目采用了与ISO 10646-1相同的字库和字码?/P>
目前两个目仍都存在Qƈ独立地公布各自的标准。Unicode协会现在的最新版本是2005q的Unicode 4.1.0。ISO的最新标准是ISO 10646-3:2003?/P>
UCS只是规定如何~码Qƈ没有规定如何传输、保存这个编码。例如“汉”字的UCS~码?C49Q我可以?个ascii数字来传输、保存这个编码;也可以用utf-8~码:3个连l的字节E6 B1 89来表C它。关键在于通信双方都要认可。UTF-8、UTF-7、UTF-16都是被广泛接受的Ҏ。UTF-8的一个特别的好处是它与ISO-8859-1完全兼容。UTF是“UCS Transformation Format”的~写?/P>
IETF的RFC2781和RFC3629以RFC的一贯风|清晰、明快又不失严}地描qCUTF-16和UTF-8的编码方法。我LC得IETF是Internet Engineering Task Force的羃写。但IETF负责l护的RFC是Internet上一切规范的基础?/P>
目前Windows的内核已l支持Unicode字符集,q样在内怸可以支持全世界所有的语言文字。但是由于现有的大量E序和文档都采用了某U特定语a的编码,例如GBKQWindows不可能不支持现有的编码,而全部改用Unicode?/P>
Windows使用代码?code page)来适应各个国家和地区。code page可以被理解ؓ前面提到的内码。GBK对应的code page是CP936?/P>
微Y也ؓGB18030定义了code pageQCP54936。但是由于GB18030有一部分4字节~码Q而Windows的代码页只支持单字节和双字节~码Q所以这个code page是无法真正用的?/P>
UCS有两U格式:UCS-2和UCS-4。顾名思义QUCS-2是用两个字节编码,UCS-4是?个字节(实际上只用了31位,最高位必须?Q编码。下面让我们做一些简单的数学游戏Q?/P>
UCS-2?^16=65536个码位,UCS-4?^31=2147483648个码位?/P>
UCS-4Ҏ最高位?的最高字节分?^7=128个group。每个group再根据次高字节分?56个plane。每个planeҎW?个字节分?56?(rows)Q每行包?56个cells。当然同一行的cells只是最后一个字节不同,其余都相同?/P>
group 0的plane 0被称作Basic Multilingual Plane, 即BMP。或者说UCS-4中,高两个字节ؓ0的码位被UCBMP?/P>
UCS-4的BMPL前面的两个零字节得CUCS-2。在UCS-2的两个字节前加上两个零字节,得CUCS-4的BMP。而目前的UCS-4规范中还没有M字符被分配在BMP之外?/P>
UTF-8是?位ؓ单元对UCSq行~码。从UCS-2到UTF-8的编码方式如下:
UCS-2~码(16q制) | UTF-8 字节?二进? |
0000 - 007F | 0xxxxxxx |
0080 - 07FF | 110xxxxx 10xxxxxx |
0800 - FFFF | 1110xxxx 10xxxxxx 10xxxxxx |
例如“汉”字的Unicode~码?C49?C49?800-FFFF之间Q所以肯定要?字节模板了:1110xxxx 10xxxxxx 10xxxxxx。将6C49写成二进制是Q?110 110001 001001Q?用这个比Ҏ依次代替模板中的xQ得刎ͼ11100110 10110001 10001001Q即E6 B1 89?/P>
读者可以用C本测试一下我们的~码是否正确。需要注意,UltraEdit在打开utf-8~码的文本文件时会自动{换ؓUTF-16Q可能生淆。你可以在设|中xq个选项。更好的工具是Hex Workshop?/P>
UTF-16?6位ؓ单元对UCSq行~码。对于小?x10000的UCS码,UTF-16~码q于UCS码对应的16位无W号整数。对于不于0x10000的UCS码,定义了一个算法。不q由于实际用的UCS2Q或者UCS4的BMP必然于0x10000Q所以就目前而言Q可以认?UTF-16和UCS-2基本相同。但UCS-2只是一个编码方案,UTF-16却要用于实际的传输,所以就不得不考虑字节序的问题?/P>
UTF-8以字节ؓ~码单元Q没有字节序的问题。UTF-16以两个字节ؓ~码单元Q在解释一个UTF-16文本前,首先要弄清楚每个~码单元的字节序。例如“奎”的Unicode~码?94EQ“乙”的Unicode~码?E59。如果我们收到UTF-16字节?94E”,那么q是“奎?q是“乙”?
Unicode规范中推荐的标记字节序的方法是BOM。BOM不是“Bill Of Material”的BOM表,而是Byte Order Mark。BOM是一个有点小聪明的想法:
在UCS~码中有一个叫?ZERO WIDTH NO-BREAK SPACE"的字W,它的~码是FEFF。而FFFE在UCS中是不存在的字符Q所以不应该出现在实际传输中。UCS规范我们在传输字节流前,先传输字W?ZERO WIDTH NO-BREAK SPACE"?/P>
q样如果接收者收到FEFFQ就表明q个字节是Big-Endian的;如果收到FFFEQ就表明q个字节是Little-Endian的。因此字W?ZERO WIDTH NO-BREAK SPACE"又被UCBOM?/P>
UTF-8不需要BOM来表明字节顺序,但可以用BOM来表明编码方式。字W?ZERO WIDTH NO-BREAK SPACE"的UTF-8~码是EF BB BFQ读者可以用我们前面介绍的编码方法验证一下)。所以如果接收者收CEF BB BF开头的字节,q道这是UTF-8~码了?/P>
Windows是使用BOM来标记文本文件的~码方式的?/P>
本文主要参考的资料?"Short overview of ISO-IEC 10646 and Unicode" (http://www.nada.kth.se/i18n/ucs/unicode-iso10646-oview.html)?/P>
我还找了两篇看上M错的资料Q不q因为我开始的疑问都找C{案Q所以就没有看:
我写qUTF-8、UCS-2、GBK怺转换的Y件包Q包括用Windows API和不使用Windows API的版本。以后有旉的话Q我会整理一下放到我的个Z上(http://fmddlmyy.home4u.china.com)?/P>
我是x楚所有问题后才开始写q篇文章的,原以Z会儿p写好。没惛_考虑措辞和查证细节花费了很长旉Q竟然从下午1:30写到9:00。希望有读者能从中受益?/P>
有的朋友Ҏ章中q句话还有疑问:
“GB2312的原文还是区位码Q从Z码到内码Q需要在高字节和低字节上分别加上A0。?/P>
我再详细解释一下:
“GB2312的原文”是指国?980q的一个标准《中华h民共和国国家标准 信息交换用汉字编码字W集 基本?GB 2312-80》。这个标准用两个数来~码汉字和中文符受第一个数UCؓ“区”,W二个数UCؓ“位”。所以也UCؓZ码?-9区是中文W号Q?6-55 区是一U汉字,56-87区是二汉字。现在Windows也还有区位输入法Q例如输?601得到“啊”。(q个Z输入法可以自动识?6q制?GB2312?0q制的区位码Q也是说输入B0A1同样会得到“啊”。)
内码是指操作pȝ内部的字W编码。早期操作系l的内码是与语言相关的。现在的Windows在系l内部支持UnicodeQ然后用代码适应各种语言Q“内码”的概念比较模p了。微软一般将~省代码|定的~码说成是内码?/P>
内码q个词汇Qƈ没有什么官方的定义Q代码页也只是微软这个公司的叫法。作为程序员Q我们只要知道它们是什么东西,没有必要q多地考证q些名词?/P>
所谓代码页(code page)是针对一U语a文字的字W编码。例如GBK的code page是CP936QBIG5的code page是CP950QGB2312的code page是CP20936?/P>
Windows中有~省代码늚概念Q即~省用什么编码来解释字符。例如Windows的记事本打开了一个文本文Ӟ里面的内Ҏ字节:BA、BA、D7、D6。Windows应该L么解释它呢Q?/P>
是按照Unicode~码解释、还是按照GBK解释、还是按照BIG5解释Q还是按照ISO8859-1去解释?如果按GBK去解释,׃得到“汉字”两个字。按照其它编码解释,可能找不到对应的字符Q也可能扑ֈ错误的字W。所谓“错误”是指与文本作者的本意不符Q这时就产生了ؕ码?/P>
{案是Windows按照当前的缺省代码页去解释文本文仉的字节流。缺省代码页可以通过控制面板的区域选项讄。记事本的另存ؓ中有一ANSIQ其实就是按照缺省代码页的编码方法保存?/P>
Windows的内码是UnicodeQ它在技术上可以同时支持多个代码c只要文件能说明自己使用什么编码,用户又安装了对应的代码页QWindowsp正确昄Q例如在HTML文g中就可以指定charset?/P>
有的HTML文g作者,特别是英文作者,认ؓ世界上所有h都用英文,在文件中不指定charset。如果他使用?x80-0xff之间的字W,中文Windows又按照缺省的GBK去解释,׃出现q。这时只要在q个html文g中加上指定charset的语句,例如Q?BR><meta http-equiv="Content-Type" content="text/html; charset=ISO8859-1">
如果原作者用的代码和ISO8859-1兼容Q就不会出现q了?/P>
再说Z码,啊的Z码是1601Q写?6q制?x10,0x01。这和计机q泛使用的ASCII~码冲突。ؓ了兼?0-7f的ASCII ~码Q我们在Z码的高、低字节上分别加上A0。这样“啊”的~码成为B0A1。我们将加过两个A0的编码也UCؓGB2312~码Q虽然GB2312的原文根本没提到q一炏V?
java.swing.border.Border
implementation . . . .
- - - -
--- --- ---
-- - -- - -- -
-- - - -- - - -- - -
摘自http://www-128.ibm.com/developerworks/cn/xml/x-BatikSvg/?ca=dwcn-newsletter-xml
陈柯
技术ȝ, 南京安元U技
2005 q?1 ?
本文是作者在 SVGGIS pȝ的开发实践过E中关于 SVG 坐标转换的ȝ。在描述 SVG 坐标变换原理的同Ӟ使用 Apache Batik 目实现了相关例子?/BLOCKQUOTE>SVG 是一U用 xml 语言来描qCl图形对象的语言QSVG 允许三种囑Ş对象Q?Q矢量图形,2Q图片,3Q文本对象。这三种囑Ş对象都可以支持分l,使用样式渲染Q进行几何变换?/P>
SVG q能够通过脚本来实C互操作和动态显C。可以通过定义动画对象或用script 脚本来实现动甅R?/P>
1.1 一?SVG 例子
?2. h文档
我们首先来看一?SVG 的例子,H口右上角有四个色块Q每个色块是一?0×50的矩形?/P>
<?xml version="1.0"?> <svg > <g> <rect x="0" y="0" width="50" height="50" style="fill:red" /> <rect x="50" y="0" width="50" height="50" style="fill:yellow" /> <rect x="0" y="50" width="50" height="50" style="fill:green" /> <rect x="50" y="50" width="50" height="50" style="fill:black" /> </g> </svg>
1.2 使用 Adobe SVG Viewer 展示?SVG 文档中实现的几何变换
~放<g transform="scale(2)">q移<g transform="translate(200 ,200)">
旋{<g transform="rotate(45)">
横切<g transform="skewX(45)">
2.1 Batik 的基知识
2.1.1 Batik 的用?/B>Batik 是基?java 语言实现的一?SVG 应用的工具集Q用于实现对 SVG 对象的显C、编辑以及将 SVG 囑Ş对象转换成其他图片格式,?jpg、gif {?/P>
q个目的目标就是给开发h员一套用于处理或应用 SVG 对象的基核心模型。作为Apache 目成员之一Q该目也ؓ开发h员提供了一个开发的可扩展的q_。同?batik 也维护了一个可以查?SVG 文g的浏览器。虽?batik q没有完全实?SVG 的所有标准语法和标记Q但通过比较不同版本的区别就会发玎ͼ他正在以很高的效率覆?SVG 所有的标准?/P>
2.1.2 让我们实C个简单的 Batik E序
首先让我们实C个简单的Z Batik ?SVG 览器。Batik 装了org.apache.batik.swing.JSVGCanvas 对象可以用于?swing 中嵌?SVG 昄容器Qƈ可以通过 org.apache.batik.swing.JSVGCanvas 提供的方法对 SVG 文档和图像进行操作。这个浏览器可以支持大部?SVG 的语法和标准包括脚本交互的功能,但暂时还没有引入动画。关于动d脚本交互的内Ҏ们会在以后的文章中讲qͼ今天先集中解军_何变换的问题?/P>
可以通过该页面引D行该E序Q?
?8. 一?SVGCanvas d到界?/B>
从附件中可以查看该程序的完整代码Q也可通过 |上下蝲地址 q行该程序?
private javax.swing.JPanel SVGPanel = new javax.swing.JPanel(); private JSVGCanvas svgCanvas = new org.apache.batik.swing.JSVGCanvas(); SVGPanel.add("Center", svgCanvas);
2.2 通过 Batik ?GVT 模型实现 SVG 的几何变?/SPAN>
2.2.1 Z么要使用 Batik 来实?SVG 的几何变?/B>当我们用 Batik 工具集作?SVG 客户端的解决ҎӞ如羃攑^U这L操作在所隑օ了。但 Batik q没有直接支持如 Adobe SVG Viewer 那样的鼠标拖动几何变换的操作Q这p求我们对q些功能q行~程处理?/P>
在分?SVG 的几何变换的l节之前Q先让我们了解一下基本的操作~程方式?/P>
2.2.2 Batik 下通过 java.awt.geom.AffineTransform 来实?SVG 的几何变?/B>
JSVGCanvas 提供Ҏ可以获取 java.awt.geom.AffineTransform 对象。AffineTransform 是用于实?D 几何囑Ş坐标变换处理的对象,可以通过该对象进行二l几何空间中两个坐标pȝ怺映射和变换?/P>
q移:
//向左和向下^U?0个像? java.awt.geom.AffineTransform rat = svgCanvas.getRenderingTransform(); rat.translate(50,50); svgCanvas.setRenderingTransform(rat);
~放:
//以屏q左上角原点为固定点q行~放操作 java.awt.geom.AffineTransform rat = svgCanvas.getRenderingTransform(); rat.scale(0.5,0.5); svgCanvas.setRenderingTransform(rat);
旋{:
//以屏q左上角原点为固定点q行旋{~放 java.awt.geom.AffineTransform rat = svgCanvas.getRenderingTransform(); rat.rotate(3.1415926/4); svgCanvas.setRenderingTransform(rat);
复合变换:
//一个综合^UR放大和旋{90度的复合变换 java.awt.geom.AffineTransform rat = svgCanvas.getRenderingTransform(); rat.translate(50Q?0); rat.scale(2Q?); rat.rotate(3.1415926/4); svgCanvas.setRenderingTransform(rat);
3.1 先来让我们通过不同的变换代码组合实现复合几何变?/SPAN>
//攑֤一倍和q移50个像素的复合变换
先让我们看第一个例?
AffineTransform rat = svgCanvas.getRenderingTransform(); rat.scale(2,2); rat.translate(50,50); svgCanvas.setRenderingTransform(rat);
可以看得出来Q这个变换的最l效果是Q图形的形状攑֤一倍,原图形的Q?Q?Q原点坐标^U?00个像素?/P>
再来看第二个例子:
//攑֤一倍和q移50个像素的复合变换 AffineTransform rat = svgCanvas.getRenderingTransform(); rat.translate(50,50); rat.scale(2,2); svgCanvas.setRenderingTransform(rat);
q个变换的最l效果是Q图形的形状攑֤一倍,原图形的Q?Q?Q原点坐标^U?0个像素?/P>
3.2 关键是顺?/SPAN>
比较一下这两种q移后的效果会发?只是因ؓ~放和^Uȝ序不同Q变换后的结果就发生了区别。第一个例子实际^Uȝ不是50个像?而是100个像素。而第二个例子则是q移?0个像素?/P>有兴的读者可以添加其他几何变换方式,q测试不同的变换序Q会发现复合变换的顺序与复合变换的最l效果是紧密相关的。那么如何分析和计算复合变换的变换结果呢Q这里我们需要补充一Ҏ学知识了?/P>
3.3 对单一的几何变换进行数学模型分?/SPAN>
对计机囑Ş学中囑Ş变换相关理论很熟悉的人可以蟩q这部分直接?Batik 的实现方式。这节用的齐次式图片引用自 SVG标准中关于坐标变换的齐次式的例子插图?首先我们来了解一下图形变换的齐次式计方法:
q是一个基本图形变换齐ơ式。等式的最双是一个坐标点未变换前的坐标矩阵,最左边是该坐标点变换后所在位|的一个三行一列的坐标矩阵Q中间那个三行三列的矩阵是变换矩阵。不同的变换方式对应不同的变换矩阵Q图形^UL果就是通过q样一个变换齐ơ式来实现的?/P>
q移:如果需要将囑Şq移QtxQtyQ个坐标Ӟ采用如下的变换矩阵带入变换方E?/P>
~放Q如果需要在 x 轴方向实?sx 倍羃放,?y 轴方向实?sy 轴羃放时Q采用如下的变换矩阵带入变换方程?/P>
旋{:如果需要将囑փ旋{ a 度时Q用如下的变换矩阵带入变换方程?/P>
3.4 采用复合几何变换的数学模型分?/SPAN>
3.4.1 数学分析当两l变换同时作用于同一个图像时Q连l用该{式Q得出如下等式。由于做变换的时候是变换矩阉|在矩늧的左边,所以对于复合变换的式子Q应该从叛_左进行读。对于如下的式子Q从双左依ơ是变换前的坐标Q第一ơ{换的转换矩阵Q第二次转换的{换矩阵,转换后的坐标倹{?/P>
q一步推?n ơ几何变换的复合变换{式Q?/P>
3.4.2 来实践一?/B>
使用q样一个复合变换方式:
<g transform="translate(50,90) rotate(-45) translate(130,160)">
Ҏ前面的分析结果带入变换方E,得出如下{式
Ҏ计算后的变换矩阵Q可得变换结果是囑Ş整体q移刎ͼ255.03,111.21Q,同时囑Ş自n沉K旉方向旋{45度。查看实际变换结果,q里我们可以发现Q对?SVG 的变换来_虽然我们习惯上从左往叛_变换参数的,实际上图形做变换的时候是从右边的变换参数开始依ơ进行图形变换的?/P>
3.5 分析一?Batik 是如何实?SVG 的复合几何变换的
3.5.1 先看W一个例子:q个变换是先攑֤后^Uȝ变换Q其变换效果最l是Q先图形的形状攑֤一倍,然后图形整个^U?00个像素。这里我们可以看出,虽然我们是先q行的放大变换,后进行的q移操作Q但当我们进行复合变换的时候由于实际运时上是先进行了q移Q后q行了羃放。或者简单的理解Z左向叛_写羃攄阵,再写q移矩阵Q这样得出的变换矩阵可以对变换后的效果q行计算了?/P>
//攑֤一倍和q移50个像素的复合变换 //<g transform=" scale(2 ) translate(50 50)"> AffineTransform rat = svgCanvas.getRenderingTransform(); rat.scale(2,2); rat.translate(50,50); svgCanvas.setRenderingTransform(rat);
我们可以这个变换对应的计算矩阵写出来:
Ҏ上面的分析我们可以看的出Q先q行~放变换在进行^Ud换的复合变换Ӟ变换后原囑օ的坐标会映射到新的位|,其中Q?/P>
X1=Sx(X+dx)
Y1=Sy(Y+dy)3.5.2 再来看第二个例子Q?/B>
q个变换是先攑֤后^Uȝ变换Q其变换效果最l是Q先图形整个^U?0个像素,然后图形的形状攑֤一倍?/P>
//攑֤一倍和q移50个像素的复合变换 //<g transform="translate(50Q?0) scale(2 )"> AffineTransform rat = svgCanvas.getRenderingTransform(); rat.translate(50,50); rat.scale(2,2); svgCanvas.setRenderingTransform(rat);
我们可以这个变换对应的 svg 文档实现写出来:
<g transform="translate(50 50) scale(2 )">
Ҏ上面的分析我们可以看的出Q先q行q移变换再进行羃攑֏换的复合变换Ӟ变换后原囑օ的坐标会映射到新的位|,其中Q?/P>
X1=Sx*X+dx
Y1=Sy*Y+dy3.5.3 实用q两个例子的成果
假设我们需要将囑Ş原点的位|移动到Q?50Q?00Q,同时形状攑֤到原来的3倍,该如何进行变换来实现q样的效果呢Q?/P>
使用W一个例子的分析l果Q先q行~放变换Q再q行q移变换的方E变换:
Ҏ推导可知需先进?倍的~放变换Q再q移Q?0Q?00Q个坐标可以实现指定的变换效果。实现程序如?/P>
//<g transform=" scale(3 ) translate(50Q?00)"> AffineTransform rat = svgCanvas.getRenderingTransform(); rat.scale(3,3); rat.translate(50,100); svgCanvas.setRenderingTransform(rat);
若先q行q移变换Q再q行~放变换的话Q根据第二个例子的推导结果:
可知应先q行Q?50Q?00Q的q移操作Q再实现3倍的~放操作。实现程序如下:
//<g transform=" translate(150Q?00) scale(3 )"> AffineTransform rat = svgCanvas.getRenderingTransform(); rat.translate(150,300); rat.scale(3,3); svgCanvas.setRenderingTransform(rat);
4. 一个常用复合变换实例的实现--定点变换
上边我们分析?Batik 实现 SVG 囑Ş变换的原理和计算Ҏ。下面我们用分析的结果实C个常用的变换实例Q定点变换。变换的U类包括~放Q旋转(一般不考虑定点q移q个概念Q?/P>所谓定点变换就是在囑Ş变换中指定一个固定的点,在变换结束后Q该点的位置不发生变化。定点变换在 GIS 的实际运用中很常见,比如地图放大到指定倍数而保持地囄某个位置Q如Q鼠标点ȝ位置Q不发生变化。我们以定点~放Z描述定点变换的用方法?/P>
假设我们?x1,y1)Ҏ做定点变换的基准点进行几何变换,要求实现变换后(x1,y1Q的位置不变?/P>
定点变换的基本思想是基于这样一个特性:当图像进行羃放,或旋转变换的时候,坐标原点的位|ƈ不发生变化。定点变换的实现Ҏ是Q先基准点Qx1,y1Q^Ud原点卛_一ơ[-x1,-y1]变换Q进行变换后再将变换后的原点q移刎ͼx1,y1Q即再进行一ơ[x1,y1]变换?/P>
实际~程的时候,我们无需对定点变换做如此复杂的运。例如可以采用如下的方式实现针对Q?0,50Q的定点变换Q?/P>
//以(50Q?0Q点为基准点q行几何变换 //<g transform="translate(50Q?0) …………?translate(-50Q?50)"> AffineTransform rat = svgCanvas.getRenderingTransform(); rat.translate(50Q?0); //其他变换方式 ……………? ……………? ……………? rat.translate(-50,-50); svgCanvas.setRenderingTransform(rat);
- 有关 SVG 的背景知识,请阅?developerWorks 上的教程Q? 可~向量图形介l?/A>"
- Scalable Vector Graphics (SVG) 1.0 Specification
- Batik目介绍 http://xml.apache.org/batik/
Pudgy's World 2005-08-20 08:55 发表评论]]>
目录
Z使用我们卛_要安装的日志记录工具Q还必须要设|操作环境,只有q样Q工h能知道从哪里扑ֈ它所需要的信息Qƈ且操作系l知道从哪里扑ֈq个工具。那么,怎样做呢Q实际上Q它要求更改操作环境。我有一些这斚w的资格文档?Configuring A Windows Working Environment ?Configuring A Unix Working Environment.
?http://jakarta.apache.org/log4j/docs/download.html下蝲log4j发行版?
解压存档文g到合适的目录中?/p>
d文g dist/lib/log4j-1.2.6.jar ?CLASSPATH 环境变量中?
日志记录?Logger)是日志处理的核心lg。log4jh5U正常?Level)?日志记录?Logger)的可用?span class="strong">Level (不包括自定义U别 Level)Q?以下内容是摘自log4j API (http://jakarta.apache.org/log4j/docs/api/index.html):
static Level DEBUG
DEBUG Level指出l粒度信息事件对调试应用E序是非常有帮助的?/p>
static Level INFO
INFO level表明 消息在粗_度U别上突出强调应用程序的q行q程?
static Level WARN
WARN level表明会出现潜在错误的情Ş?/p>
static Level ERROR
ERROR level指出虽然发生错误事gQ但仍然不媄响系l的l箋q行?/p>
static Level FATAL
FATAL level指出每个严重的错误事件将会导致应用程序的退出?/p>
另外Q还有两个可用的特别的日志记录? (以下描述来自log4j API http://jakarta.apache.org/log4j/docs/api/index.html):
static Level ALL
ALL Level是最低等U的Q用于打开所有日志记录?
static Level OFF
OFF Level是最高等U的Q用于关闭所有日志记录?
日志记录器(LoggerQ的行ؓ是分{的。如下表所C:
有很多方法可以创Z个日志记录器QLoggerQ,下面Ҏ可以取回root日志记录?
Logger logger = Logger.getRootLogger(); |
Logger logger = Logger.getLogger("MyLogger"); |
static Logger logger = Logger.getLogger(test.class); |
所有这些创建的?logger"的日志记录器都可以用下面Ҏ讄U别:
logger.setLevel((Level)Level.WARN); |
Appender 控制日志怎样输出。下面列Z些可用的Appender(log4j API中所描述?http://jakarta.apache.org/log4j/docs/api/index.html):
ConsoleAppender:使用用户指定的布局(layout) 输出日志事g到System.out或?System.err。默认的目标是System.out?
DailyRollingFileAppender 扩展FileAppenderQ因此多个日志文件可以以一个用户选定的频率进行@环日志记录?
FileAppender 把日志事件写入一个文?
RollingFileAppender 扩展FileAppender备䆾定w辑ֈ一定大的日志文g?/p>
WriterAppenderҎ用户的选择把日志事件写入到Writer或者OutputStream?
SMTPAppender 当特定的日志事g发生Ӟ一般是指发生错误或者重大错误时Q发送一邮件?
SocketAppender l远E日志服务器Q通常是网l套接字节点Q发送日志事ӞLoggingEventQ对象?/p>
SocketHubAppender l远E日志服务器组Q通常是网l套接字节点Q发送日志事ӞLoggingEventQ对象?/p>
SyslogAppenderl远E异步日志记录的后台_E序(daemon)发送消息?
TelnetAppender 一个专用于向只ȝl套接字发送消息的log4j appender?
q可以实?Appender 接口Q创Z自己的方式进行日志输出的Appender?
ConsoleAppender appender = new ConsoleAppender(new PatternLayout()); |
FileAppender appender = null; |
FileAppender(Layout layout, String filename) |
FileAppender(Layout layout, String filename, boolean append) |
WriterAppender appender = null; |
q里是一个非常简单的例子Q程序实CSimpleLayout和FileAppender:
import org.apache.log4j.Level; |
你可以下? simpandfile.java?q可以查看它的输出: output1.txt.
q里是一个非常简单的例子Q程序实C HTMLLayout和WriterAppender:
import java.io.*; |
你可以下? simpandfile.java. q可以查看它的输出:output1.txt.
q里是一个非常简单的例子Q程序实CPatternLayout和ConsoleAppender:
import org.apache.log4j.Level; |
你可以下?simpandfile.java. q可以查看它的输出: output2.txt.
Log4jl常与外部日志文件联合用,q样很多可选项不必编码在软g中。用外部配|文件的优点是修改可选项不需要重新编译程序。唯一的缺点就是,׃用到io 指oQ速度E微有些减慢?
有两个方法可以用来指定外部配|文Ӟ文本文g或者XML文g。既然现在所有事情都写成XML文gQ那么该教程重点讲解XML文gҎQ但是也包含相关文本文g的例子。首先,看看下面的XML配置文gCZQ?/a>
<?xml version="1.0" encoding="UTF-8" ?> |
<appender name="ConsoleAppender" class="org.apache.log4j.ConsoleAppender"> |
<root> |
DOMConfigurator.configure("configurationfile.xml"); |
DOMConfigurator 用一DOM树来初始化log4j环境。这里是CZ中的XML配置文gQ?/a>plainlog4jconfig.xml。这里是执行该配|文件的E序: files/externalxmltest.java:
import org.apache.log4j.Logger; |
q里是一个实现带?span class="emphasis">PatternLayout?span class="emphasis">FileAppender的日志记录器Logger的XML配置文g:
<?xml version="1.0" encoding="UTF-8" ?> |
你可以从q里下蝲CZ: xmllog4jconfig2.xml?惌得到更多的用XML文g配置log4j环境的例子,h看log4j发行版的目录src/java/org/apache/log4j/xml/examples/ ?
q就是上面讨论的文本文g形式的配|文?
# initialise root logger with level DEBUG and call it BLAH |
从这里可以下? plainlog4jconfig.txt。这是执行该配|文件的E序:
import org.apache.log4j.Logger; |
你可以下载用该配置文g的示例: externalplaintest.java。想要获得更多的使用文本文g配置log4j环境的例子,h看log4j发行版中的目录examples?
使用外部配置文g的例子就单的讨论到这里,现在应该可以肯定你已l有能力独立学习更多的log4j发行版和试版中提供的例子?/p>
http://jakarta.apache.org/log4j/docs/manual.html
log4j的简明介l?- Ceki G- 2002q??/p>
http://www.vipan.com/htdocs/log4jhelp.html
不要用System.out.printlnQ用Log4j - Vipan Singla
http://www.opensymphony.com/guidelines/logging.jsp
LOG4J / OpenSymphony日志记录入门
http://builder.com.com/article.jhtml?id=u00820020124kev01.htm
l你的Java应用E序d日志记录 - Kevin Brown
在后面的两年里我l自己定下了几个目标Q?
一.努力做好本职工作Q在工作上得到公司和同事们的认同Q?
?努力学习ICg设计知识Q多向同事请教,q利用一切机会多实践Q?
?实现我的实时操作pȝ的主要部分,完成TCP/IP协议栈模块,q免费发布源代码Q?
?和我x友结婚ƈC套小房子Q这是最重要的,因ؓ我明白事业是可以重来的,但是珍贵的感情很隑֤而复得?
q里提一下我现在开发的操作pȝQ它是一个实时嵌入式pȝQ目前支持以下特性:
a.支持旉片轮转调度和Z优先U调度,最?4个优先Q?
b.抢占式实时内核;
c.Z便于ULQ主体用标准C实现Q?
d.汇编代码非常,不到100行;
e.支持d理Q各d有独立的堆栈Q?
f.q程同步和通信目前完成了SemaphoreQMessage Queue正在调试Q?
g.实现了定时系l调用;
h.可以在windows上仿真调?
我还打算下一步实C先反{保护QEvent FlagQData PipeQ内存管理(以前实现q)、驱动接口等?在这之后我还会努力完善它Q比如加入文件系l,协议栈、调试接口等。希望朋友们提出自己的意见和Q在此不胜感ȀQ?
后记Q?
像有的朋友说的Q我的经历或怼l一些朋友生误|在这里我必须说明一下?我来上v以前学习q于拼命Q常常晚上只?个多时Q我w高1c?1Q那时只?08斤(我现?30多)Q家Z说我q样拼命zMq?0岁,但是当时的我太固执,我对他们说只要能实现理想z?0岁我够了。那时的拼命使我的n体受C影响Q有一ơ早上突然腰肌剧痛难忍,痛的我倒在床上站不h。虽然我现在已经比较注意Q但有时候还会隐隐作痛。后来在x友说服了我,来上以后我不再如此。我l常引用父亲的一句话“n体是革命的本钱”?BR> 而且我也发现拼命不是办法Q我可以熬一两个通宵Q最多的一ơ我q箋工作了三天三夜, 但是我半个月都没有恢复过来,q样是不是得不偿失?学习工作应该是一个长期的q程Q?像马拉松而不是百c_刺。我现在非常注意调整学习和工作的强度Q我要保证每天尽量有相对充沛的精力,一些年ȝ朋友觉得自己也应该拼命努力,q让我多有些担心,如果我的故事能让你在学习工作上多一点兴,我会感到很开心,但如果误g某些朋友Q让你做一些不值得的付出,我会感到很内疚?BR> 技术没有贵׃分,我以前换行业是因q兴趣所_而不是对哪个行业有什么偏见。我希望我的l历不要l朋友一个错误的导向Q觉得我始终向更高的技术发展。其实各行各业做到顶都是很困难的。话又说回来虽然技术没有贵贱,但是门槛是有高低的, 无论如何Q做IC的门槛要比做|页的高Q这一Ҏ可否认。国家各Uh才都是需要的Q但是作Z人奋发向上的xq是应该有的Q努力在自己喜欢的行业上做的更好Q而不应该停留在比较肤的层次上?BR> 我是一个自p得比较有自知之明的hQ或许我最大的优点是知道自己有很多缺?Q)。我的故事中很多的曲折和错误都是由我的缺炚w成的,希望大家用审慎的眼光看待我的l历Q不要被我的“花a巧语”所qh。我学习有些随心所Ԍq给我带来了无尽的麻烦,也大大阻的我的发展。记得我时候成l比较出Ԍ但是后来学习严重偏科Q导致我中学成W一再滑坡,也没有考上什么好的学校,时候的一个朋友,当时的成l和我相仿,但是没有我这个缺点,她上了清华,后来在去了美国深造,在一个著名导师手下研I理论科学,q未不是一条更好的\。另外我的学习方法也是在不断改善中的Q过ȝ学习q于讲究数量和时_那样学习既苦而已效率不高Q现在我非常注意学习的效率和技巧,q样才是学习的捷径(当然不是指投机取巧)Q比如说学一相对陌生的技术,如果有条Ӟ不妨问一问有l验的hQ不需要问很多Q往往他不l意的几句话会给你非常大的帮助,甚至过你看一个星期的书。带着q样的思想再去学习你会节省很多旉Q这样何乐不为呢Q这些年中我学了不少的东西,׃开始非常盲目,所以学的东西杂乱无章,现在回想h让我啼笑皆非Q我把大量的旉费在一些没有必要深入了解的知识上,毕竟一个h的精力是有限度的。很多朋友很我一样都背过五笔字ŞQ的它是个不错的输入法Q但是对一个研发h员它l对不值得你去背,你的旉应该花在有h值的地方。我q样的事情还做过很多Q我背过CCED、WPS的命令和快捷键,在dBase基本退出历史舞台后我还׃很多旉d习它的用。所以我的学习在前期~Z规划Q没有明的短期目的、中期目标,只有一个虚无飘渺的长期的理惟뀂这像做设计一P好的设计是从需求抽象到代码有很多过E,而不能得C需求就立刻开始开始编码?
当然q么些年的学习和工作多多少有些收获Q下面我说说我的一些学习的心得Q这 些方法未必正,我也在不断探索和改进中。我的学习和工作有相Ҏ的目标Q我不会一时心动而去学习某一技术,在下军_之前我会考虑很多Q包括长期的发展Q个\U的规划Q需要付出的代h、可能遇到的困难及解决的办法{等Q在军_后还会制定更加明的计划Q包括短期、中期和长期的,w边可以利用到的资源Q包括好的书c、资料、Yg环境Q也包括有经验的朋友或者师长)Q以及每一个阶D|怎么q渡到高一阶段的计划,往往在一个学习阶D一旦上路后会走的相寚w利,但是跨阶D通常比较ȝQ比如从学习基础知识转到实践。另外我C也有自己的方法,现在世面上高质量的书q不如低质量书多Q对于一个陌生的技术,往往在第一ơ买书会选择错误Q即使买C本好书但是它的方向也未必适合你,所以我通常会先在网上查找一些该技术的介绍Q有了一点点概念后再M一本比较薄、相对便宜ƈ且内容相Ҏ泛而谈的书Q这是国内作者最善于写的书:Q?Q再把它览一遍后我就会基本明白这门技术的要点Q后面买书和制定计划׃明确的多。否则一开始就x本好书往往比较困难Q而且买回来后努力学习Q有时候学了一半才发现是本低质量的书或者是相对q时技术,让h非常懊恼。另外让有经验的人帮你介l,通常也是一个不错的选择?BR> 有些朋友惛_通信、嵌入式开发,但总觉得自己没有Yg环境Q我按我的了解l?大家介绍一下怎么建立q样的环境,当然我了解的只是我学习和工作的方向。通信我做的是数据|方面的工作Q包括TCP/IP、二三层交换、对接入|、H.323和Y交换也有一点认识。这些Yg环境都是可以在PC上构建的。你甚至可以在一个没有网卡的PC上徏立一个包含多个\由器、接入服务器、VoIP|关、网守、主机等的仿真网l环境,而且与实际的|络相当接近Q当然这需要你有清晰的|络概念和一定的|络知识Q我一直在努力开发一套Y件将q个q程化,目前试验已经做完Q我可能会将它融入我的操作系l外围扩展Y件中。这LҎ我无法用单的语句讲的很清楚,我可以说一下大概的思想Q就是在PC上实C真网卡,Q知道Windows怎么在没有网卡的机器实现虚拟|卡技术的朋友都应该会明白Q,然后每一个仿真网卡对应一个虚拟设备,如\由器或者主机。你也可以借助W三方工具完成部分工作,如VmWare{。我现在是利用一个仿真网卡做自己的开发的?BR> 至于嵌入式开发环境更加容易实玎ͼPC是一个非常大的硬件^収ͼ现有的嵌入式?作系l通常都支持X86Q你可以在上面做开发,通过软盘Boot或者用虚拟机装蝲Q我用VxWorks做了试验Q在一台PC上跑Windows和VxWorks两个pȝ。另外Windows上的兼容DOS?6位仿真X86环境也ؓ很多操作pȝ提供了绝佳的试验环境Q我的操作系l在Windows上就是这样实现的。Linux在嵌入式中应用也比较q泛Q它在网上有大量的资料,而且也相Ҏ较容易实c同时很多完善的嵌入式开发环境支持Y件仿真,如Tornado、WinCE{?
很多初学者不是很理解Z么mainҎ一定要q样来定义public static void main(String[] args)Q能不能不这样写Q包括我刚学习Java的时候也有这L疑问。想知道{案吗?很简单,你把main改个名字q行一下,看看报什么错误,然后Ҏ出错信息q行分析Q把main的public取掉Q在试试看,报什么错误;staticLq能不能q行Q不知道mainҎ是否一定要传一个String[]数组的,把String[]ҎQ改成int[]Q或者String试试看;不知道是否必dargs参数名称的,也可以把argsҎ别的名字Q看看运行结果如何?nbsp;
我当初学习Java的时候就是这样做的,把Hello WorldE序反复改了七八ơ,不断q行Q分析运行结果,最后就d明白Z么了mainҎ是这样定义的了?nbsp;
此外Q我对于staicQpublicQprivateQExceptionQtry{ }catch {}finally{}{等{等一开始都不是很懂Q都是把参考书上面的例子运行成功,然后开始破坏它Q不断的Ҏ自己心里面的疑问来重新改写程序,看看能不能运行,q行出来是个什么样子,是否可以得到预期的结果。这栯然比较费旉Q不q一个例子程序这样反复破坏几ơ之后。我对q个相关的知识彻底学通了。有时候甚x意写一些错误的代码来运行,看看能否得到预期的运行错误。这样对于编E的掌握是及其深ȝ?nbsp;
其中特别值得一提的是JDK有一个非常棒的调试功能,-verbose
java -verbose
javac -verbose 以及其它很多JDK工具都有q个选项
-verbose 可以昄在命令执行的q程中,JVM都依ơ加载哪里ClassQ通过q些宝贵的调试信息,可以帮助我们分析出JVM在执行的q程中都q了些什么?nbsp;
另外Q自己在学习q程中,写的很多的这U破坏例E,应该有意识的分门别类的保存下来,在工作中U篏的典型例E也应该定期整理Q日U月累,自己有了一个代码库了。遇到类似的问题Q到代码库里?nbsp;Copy & Paste QSearch & ReplaceQ就好了Q极大提高了开发速度。最理想的情冉|把一些通用的例E自己再抽象一层,形成一个通用的类库,装好。那么可复用性就更强了?nbsp;
所以我觉得其实不是特别需要例E的Q自己写的破坏例E就是最好的例子Q如果你实在对自己写的代码不攑ֿ的话Q我强烈推荐你看看JDK基础cd的Java源代码。在JDK安装目录下面会有一个src.zipQ解开来就可以完整的看到整个JDK基础cdQ也是rt.jar的Java源代码,你可以参考一下Sun是怎么写JavaE序的,规范是什么样子的。我自己在学习Java的类库的时候,当有些地方理解的不是很清楚的时候,或者想更加清晰的理解运作的l节的时候,往往会打开相应的类的源代码Q通过看源代码Q所有的问题都会一扫而空?nbsp;
Java Learning PathQ五Q资源篇
1?nbsp;http://java.sun.com/ (英文)
Sun的Java|站Q是一个应该经常去看的地方。不用多说?nbsp;
2?nbsp;http://www-900.ibm.com/developerWorks/cn/
IBM的developerWorks|站Q英语好的直接去英文ȝ点看。这里不但是一个极好的面向对象的分析设计网站,也是Web ServicesQJavaQLinux极好的网站。强烈推荐!Q!
3?nbsp;http://www.java-cn.com/ (中文)
JAVA中文站,目前国内资料最全、会员最多的JAVA技术网站,人气极高。有《JAVA电子书库》、《JAVA视频库?国内唯一)、《JAVA技术文摘库》、《JAVA源代码库》、《JAVA工具库》、《招聘求职广场》等主要栏目Q还有一些专家栏目。目前会员有5万多QVIP会员q?000人。无论是菜鸟q是老鸟Q都能在此网站中扑ֈ自己所需要的东东Q! 最强烈推荐Q!Q!Q!
4?nbsp;http://www.javaworld.com/ (英文)
关于Java很多新技术的讨论和新闅R想多了解Java的方斚w面的应用Q这里比较好?nbsp;
5?nbsp;http://dev2dev.bea.com.cn/index.jsp
BEA的开发者园圎ͼBEA作ؓ最重要的App Server厂商Q有很多独到的技术,在Weblogic上做开发的朋友不容错过?nbsp;
6?nbsp;http://www.huihoo.com/
灰狐动力|站Q一个专业的中间件网站,虽然不是专业的Java|站Q但是在J2EE企业应用技术方面有深厚的造诣?nbsp;
7?nbsp;http://www.theserverside.com/home/ (英文)
TheServerSide是一个著名的专门面向Java Server端应用的|站?nbsp;
8?nbsp;http://www.javaresearch.org/
Java研究l织Q有很多优秀的Java斚w的文章和教程Q特别是在JDO斚w的文章比较丰富?nbsp;
9?nbsp;http://www.cnjsp.org/
JSP技术网站,有相当多的Java斚w的文章和资源?nbsp;
10?nbsp;http://www.jdon.com/
Jdon论坛Q是一个个人性质的中文J2EE专业技术论坛,在众多的Java的中文论坛中QJdon一个是技术含量非帔RQ帖子质量非常好的论坛?nbsp;
11?nbsp;http://sourceforge.net/
SourgeForge是一个开放源代码软g的大本营Q其中也有非帔R怸富的Java的开放源代码的著名的软g?/P>