<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-38574248</id><updated>2012-05-15T07:04:11.405+08:00</updated><category term='powerpoint'/><category term='J2ME'/><category term='指针'/><category term='鼠标'/><category term='java'/><category term='note'/><category term='学习资料'/><category term='蓝牙'/><category term='事件模型'/><category term='struct'/><category term='模板'/><category term='NetBeans'/><category term='blog'/><category term='多线程'/><category term='日志'/><category term='Vi'/><category term='JACOB'/><category term='键盘'/><category term='jni'/><category term='JPS'/><category term='Java Web Start'/><category term='测试'/><category term='PAN'/><category term='Bluetooth'/><category term='单元测试'/><category term='毕业设计'/><category term='MIDlet'/><category term='笔记'/><category term='lcdui'/><category term='c语言'/><category term='c++'/><category term='调试'/><title type='text'>小人物的Blog</title><subtitle type='html'>随便写写吧</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://zjharry.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38574248/posts/default'/><link rel='alternate' type='text/html' href='http://zjharry.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Harry</name><uri>http://www.blogger.com/profile/14571187675245178578</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>19</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-38574248.post-4701571801890483281</id><published>2007-03-23T14:41:00.000+08:00</published><updated>2007-03-23T15:11:14.767+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='powerpoint'/><category scheme='http://www.blogger.com/atom/ns#' term='JACOB'/><category scheme='http://www.blogger.com/atom/ns#' term='NetBeans'/><title type='text'>使用JACOB控制Powerpoint</title><content type='html'>&lt;p&gt;&lt;strong&gt;&lt;span style="font-size:130%;"&gt;什么是JACOB？&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;JACOB是一个JAVA和COM之间的桥接口。它使得你可以在Java中自动控制COM组件。它使用JNI实现本地调用COM和Win32程序接口。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;span style="font-size:130%;"&gt;除了JACOB，还需要什么？&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;要实现控制powerpoint除了了解JACOB怎么使用外，还需要了解powerpoint对象模型和powerpoint提供的接口。具体这方面的信息可以在MSDN上查找到。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;span style="font-size:130%;"&gt;简单实例&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;我实现了一个打开powerpoint程序并播放一个幻灯片的小程序，仅供大家参考。&lt;/p&gt;&lt;p&gt;/*&lt;/p&gt;&lt;p&gt;* PPTTest.java &lt;/p&gt;&lt;p&gt;* * Created on 2007年3月23日, 下午1:34&lt;/p&gt;&lt;p&gt;* * To change this template, choose Tools Template Manager &lt;/p&gt;&lt;p&gt;* and open the template in the editor. &lt;/p&gt;&lt;p&gt;*/&lt;br /&gt;package jacobdemo;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;import com.jacob.activeX.ActiveXComponent;&lt;/p&gt;&lt;p&gt;import com.jacob.com.ComThread;&lt;/p&gt;&lt;p&gt;import com.jacob.com.Dispatch;&lt;/p&gt;&lt;p&gt;import com.jacob.com.Variant;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;/** &lt;/p&gt;&lt;p&gt;* * @author Xiaofeng Wang &lt;/p&gt;&lt;p&gt;*/&lt;/p&gt;&lt;p&gt;public class PPTTest { &lt;/p&gt;&lt;p&gt;private static final String PPT_FILE = "D:\\ajax.ppt"; &lt;/p&gt;&lt;p&gt;/** &lt;/p&gt;&lt;p&gt;* @param args the command line arguments &lt;/p&gt;&lt;p&gt;*/ &lt;/p&gt;&lt;p&gt;public static void main(String[] args) { &lt;/p&gt;&lt;p&gt;// 新建一个powerpoint程序实例 &lt;/p&gt;&lt;p&gt;ActiveXComponent ppt = new ActiveXComponent("PowerPoint.Application"); &lt;/p&gt;&lt;p&gt;// 设置程序界面是否可见 &lt;/p&gt;&lt;p&gt;ppt.setProperty("Visible", new Variant(true)); &lt;/p&gt;&lt;p&gt;ActiveXComponent presentations &lt;/p&gt;&lt;p&gt;= ppt.getPropertyAsComponent("Presentations"); &lt;/p&gt;&lt;p&gt;// 打开一个现有的 Presentation 对象 &lt;/p&gt;&lt;p&gt;ActiveXComponent presentation = &lt;/p&gt;&lt;p&gt;presentations.invokeGetComponent("Open",new Variant(PPT_FILE), &lt;/p&gt;&lt;p&gt;new Variant(true)); &lt;/p&gt;&lt;p&gt;// powerpoint幻灯展示设置对象 &lt;/p&gt;&lt;p&gt;ActiveXComponent setting = presentation.getPropertyAsComponent("SlideShowSettings"); &lt;/p&gt;&lt;p&gt;// 调用该对象的run函数实现全屏播放 &lt;/p&gt;&lt;p&gt;setting.invoke("Run"); &lt;/p&gt;&lt;p&gt;// 释放控制线程 &lt;/p&gt;&lt;p&gt;ComThread.Release(); &lt;/p&gt;&lt;p&gt;} &lt;/p&gt;&lt;p&gt;}&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;span style="font-size:130%;"&gt;相关资料&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;powerpoint相关 &lt;a href="http://msdn.microsoft.com/library/chs/default.asp?url=/library/CHS/modcore/html/deovrworkingwithpresentationobject.asp"&gt;http://msdn.microsoft.com/library/chs/default.asp?url=/library/CHS/modcore/html/deovrworkingwithpresentationobject.asp&lt;/a&gt;&lt;/li&gt;&lt;li&gt;JACOB mail-list上的一篇文章 &lt;a href="http://tech.groups.yahoo.com/group/jacob-project/message/4988"&gt;http://tech.groups.yahoo.com/group/jacob-project/message/4988&lt;/a&gt;&lt;/li&gt;&lt;li&gt;JACOB的网站 &lt;a href="http://danadler.com/jacob/"&gt;http://danadler.com/jacob/&lt;/a&gt; &lt;a href="http://sourceforge.net/projects/jacob-project/"&gt;http://sourceforge.net/projects/jacob-project/&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38574248-4701571801890483281?l=zjharry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zjharry.blogspot.com/feeds/4701571801890483281/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38574248&amp;postID=4701571801890483281' title='2 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38574248/posts/default/4701571801890483281'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38574248/posts/default/4701571801890483281'/><link rel='alternate' type='text/html' href='http://zjharry.blogspot.com/2007/03/jacobpowerpoint.html' title='使用JACOB控制Powerpoint'/><author><name>Harry</name><uri>http://www.blogger.com/profile/14571187675245178578</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38574248.post-3030244195959574729</id><published>2007-03-22T12:52:00.000+08:00</published><updated>2007-03-22T12:53:47.925+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Vi'/><category scheme='http://www.blogger.com/atom/ns#' term='NetBeans'/><title type='text'>Vi指令大全[转]</title><content type='html'>进入vi的命令&lt;br /&gt;vi filename: 打开或新建文件，并将光标置于第一行首&lt;br /&gt;vi +n filename: 打开文件，并将光标置于第n行首&lt;br /&gt;vi + filename: 打开文件，并将光标置于最后一行首&lt;br /&gt;vi +/pattern filename: 打开文件，并将光标置于第一个与pattern匹配的串处&lt;br /&gt;vi -r filename: 在上次正用vi编辑时发生系统崩溃，恢复filename&lt;br /&gt;vi filename....filename: 打开多个文件，依次进行编辑&lt;br /&gt;&lt;br /&gt;移动光标类命令&lt;br /&gt;h: 光标左移一个字符&lt;br /&gt;l: 光标右移一个字符&lt;br /&gt;space: 光标右移一个字符&lt;br /&gt;Backspace: 光标左移一个字符&lt;br /&gt;k或Ctrl+p: 光标上移一行&lt;br /&gt;j或Ctrl+n: 光标下移一行&lt;br /&gt;Enter: 光标下移一行&lt;br /&gt;w或W : 光标右移一个字至字首&lt;br /&gt;b或B : 光标左移一个字至字首&lt;br /&gt;e或E : 光标右移一个字至字尾&lt;br /&gt;): 光标移至句尾&lt;br /&gt;(: 光标移至句首&lt;br /&gt;}: 光标移至段落开头&lt;br /&gt;{: 光标移至段落结尾&lt;br /&gt;nG: 光标移至第n行首&lt;br /&gt;n+: 光标下移n行&lt;br /&gt;n-: 光标上移n行&lt;br /&gt;n$: 光标移至第n行尾&lt;br /&gt;H: 光标移至屏幕顶行&lt;br /&gt;M: 光标移至屏幕中间行&lt;br /&gt;L: 光标移至屏幕最后行&lt;br /&gt;0: 光标移至当前行首&lt;br /&gt;$: 光标移至当前行尾&lt;br /&gt;&lt;br /&gt;屏幕翻滚类命令&lt;br /&gt;Ctrl+u: 向文件首翻半屏&lt;br /&gt;Ctrl+d: 向文件尾翻半屏&lt;br /&gt;Ctrl+f: 向文件尾翻一屏&lt;br /&gt;Ctrl＋b: 向文件首翻一屏&lt;br /&gt;nz: 将第n行滚至屏幕顶部，不指定n时将当前行滚至屏幕顶部。&lt;br /&gt;&lt;br /&gt;插入文本类命令&lt;br /&gt;i: 在光标前&lt;br /&gt;I: 在当前行首&lt;br /&gt;a: 光标后&lt;br /&gt;A: 在当前行尾&lt;br /&gt;o: 在当前行之下新开一行&lt;br /&gt;O: 在当前行之上新开一行&lt;br /&gt;r: 替换当前字符&lt;br /&gt;R: 替换当前字符及其后的字符，直至按ESC键&lt;br /&gt;s: 从当前光标位置处开始，以输入的文本替代指定数目的字符&lt;br /&gt;S: 删除指定数目的行，并以所输入文本代替之&lt;br /&gt;ncw或nCW: 修改指定数目的字&lt;br /&gt;nCC: 修改指定数目的行&lt;br /&gt;&lt;br /&gt;删除命令&lt;br /&gt;ndw或ndW: 删除光标处开始及其后的n-1个字&lt;br /&gt;do: 删至行首&lt;br /&gt;d$: 删至行尾&lt;br /&gt;ndd: 删除当前行及其后n-1行&lt;br /&gt;x或X: 删除一个字符，x删除光标后的，而X删除光标前的&lt;br /&gt;Ctrl+u: 删除输入方式下所输入的文本&lt;br /&gt;&lt;br /&gt;搜索及替换命令/pattern: 从光标开始处向文件尾搜索pattern&lt;br /&gt;?pattern: 从光标开始处向文件首搜索pattern&lt;br /&gt;n: 在同一方向重复上一次搜索命令&lt;br /&gt;N: 在反方向上重复上一次搜索命令&lt;br /&gt;:s/p1/p2/g: 将当前行中所有p1均用p2替代&lt;br /&gt;:n1,n2s/p1/p2/g: 将第n1至n2行中所有p1均用p2替代&lt;br /&gt;:g/p1/s//p2/g: 将文件中所有p1均用p2替换&lt;br /&gt;&lt;br /&gt;选项设置&lt;br /&gt;all: 列出所有选项设置情况&lt;br /&gt;term: 设置终端类型&lt;br /&gt;ignorance: 在搜索中忽略大小写&lt;br /&gt;list: 显示制表位(Ctrl+I)和行尾标志($)&lt;br /&gt;number: 显示行号&lt;br /&gt;report: 显示由面向行的命令修改过的数目&lt;br /&gt;terse: 显示简短的警告信息&lt;br /&gt;warn: 在转到别的文件时若没保存当前文件则显示NO write信息&lt;br /&gt;nomagic: 允许在搜索模式中，使用前面不带“\”的特殊字符&lt;br /&gt;nowrapscan: 禁止vi在搜索到达文件两端时，又从另一端开始&lt;br /&gt;mesg: 允许vi显示其他用户用write写到自己终端上的信息&lt;br /&gt;&lt;br /&gt;最后行方式命令:n1,n2 co n3: 将n1行到n2行之间的内容拷贝到第n3行下&lt;br /&gt;:n1,n2 m n3:将n1行到n2行之间的内容移至到第n3行下&lt;br /&gt;:n1,n2 d: 将 n1行到n2行之间的内容删除&lt;br /&gt;:w: 保存当前文件&lt;br /&gt;:e filename: 打开文件filename进行编辑&lt;br /&gt;:x: 保存当前文件并退出&lt;br /&gt;:q: 退出vi&lt;br /&gt;:q!: 不保存文件并退出vi&lt;br /&gt;:!command: 执行shell命令command&lt;br /&gt;:n1,n2 w!command: 将文件中n1行至n2行的内容作为command的输入并执行之， 若不指定n1，n2，则表示将整个文件内容作为command的输入&lt;br /&gt;:r!command: 将命令command的输出结果放到当前行&lt;br /&gt;&lt;a name=".E5.AF.84.E5.AD.98.E5.99.A8.E6.93.8D.E4.BD.9C"&gt;&lt;/a&gt;&lt;br /&gt;寄存器操作&lt;br /&gt;"?nyy: 将当前行及其下n行的内容保存到寄存器？中，其中?为一个字母，n为一个数字&lt;br /&gt;"?nyw: 将当前行及其下n个字保存到寄存器？中，其中?为一个字母，n为一个数字&lt;br /&gt;"?nyl: 将当前行及其下n个字符保存到寄存器？中，其中?为一个字母，n为一个数字&lt;br /&gt;"?p: 取出寄存器？中的内容并将其放到光标位置处。这里？可以是一个字母，也可以是一个数字&lt;br /&gt;ndd: 将当前行及其下共n行文本删除，并将所删内容放到1号删除寄存器中&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38574248-3030244195959574729?l=zjharry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zjharry.blogspot.com/feeds/3030244195959574729/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38574248&amp;postID=3030244195959574729' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38574248/posts/default/3030244195959574729'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38574248/posts/default/3030244195959574729'/><link rel='alternate' type='text/html' href='http://zjharry.blogspot.com/2007/03/vi.html' title='Vi指令大全[转]'/><author><name>Harry</name><uri>http://www.blogger.com/profile/14571187675245178578</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38574248.post-6634818730579952643</id><published>2007-03-16T20:06:00.000+08:00</published><updated>2007-03-17T15:28:33.757+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JPS'/><category scheme='http://www.blogger.com/atom/ns#' term='Java Web Start'/><category scheme='http://www.blogger.com/atom/ns#' term='Bluetooth'/><category scheme='http://www.blogger.com/atom/ns#' term='NetBeans'/><title type='text'>增强了Java的功能的Cool APIs</title><content type='html'>一篇比较旧的文章&lt;br /&gt;2001年6月8号，Java保持在内容和功能的增强。Java公社（JCP）的参与者们又一次构造和提交了一些新的API。事实上，在今年的JavaOne会议上，JCP组织扮演了重要的角色。在每个会议上，演讲人都提及Java请求规范（JSR），提交规范，以及列举他们组织的参与者。Sun的人员拿走了首要荣誉，但大家清楚地知道是全世界的组织捐赠出了JCP的成就。&lt;br /&gt;在这篇文章中，我将介绍3个最酷的在会议上讨论的API：&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Java打印服务(JPS)&lt;/li&gt;&lt;li&gt;无线设备连接(Bluetooth)&lt;/li&gt;&lt;li&gt;远程客户端加载(Java Web Start)&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Java打印服务(JPS)&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;尽管Java早就支持打印API了，但他们注重通过图形来设置页面。如果你是个图形方面的天才，那不成问题，但对于普通人来说太难使用了。JDK1.4出现了一个新包javax.print，使得查找打印机和向打印机发送文档相当的简单。&lt;/p&gt;&lt;p&gt;这个API是基于Xerox提交的JSR，它提供了基于打印机的名称、地址或性能来查找打印机。它也提供了机制用于指定打印的份数，需要单面还是双面打印，及纸张大小。Java打印服务接口支持所有国际标准的纸张大小，包括European A4,US letter,和Asian B5。&lt;/p&gt;&lt;p&gt;在JPS中，数据格式使用MIME类型指定，例如:image/jpeg,text/plain,及text/html。最棒的是这个API包含一个能识别HTML的格式引擎，它需要一个实现Printable或Pageable接口的文档，并且生成PostScript。HTML格式化引擎对于流行的XML数据存储具有很大的价值。你只需要设置一个XSLT（可扩展样式表语言转换）样式表，使用它把XML数据转换成HTML，然后把结果发送给打印机就可以了。&lt;/p&gt;&lt;p&gt;尽管打印接口包含了PostScript格式化引擎，但它没有实现PDF格式生成器。然而，提供了相应的说明，我估计实现PDF输出已经不远了。&lt;/p&gt;&lt;p&gt;这个打印接口还有很多缺陷使得它不够完整得像一个商业产品，没有一个独立软件提供商愿意去生产它。例如：缺乏打印预览功能及在打印过程中转换托盘。&lt;/p&gt;&lt;p&gt;托盘转换是很重要的，当你想要指定信纸上打印一行时，当在打印普通纸张时停顿一下时。你当然也需要打印预览，当你想要使用户看到打印后的效果。&lt;/p&gt;&lt;p&gt;自从2D图形包提供了打印预览功能，及托盘转换是一个简单精致的接口，很可能将来在一些打印机上实现。然而，现在并没有这方面的计划。&lt;/p&gt;&lt;p&gt;尽管优雅的商业应用程序仍然缺乏他们需要的功能，实用程序的开发人员可以使用他们需要的打印功能了。事实上使用得java打印接口成为了受欢迎的新功能。&lt;/p&gt;&lt;p&gt;无线设备互联(Bluetooth)&lt;/p&gt;&lt;p&gt;Java版的蓝牙接口仍处于初级阶段，但是他们在继续完善。&lt;/p&gt;&lt;p&gt;蓝牙致力于近距离的动态设备互联--大概30英尺左右。它运行在相当廉价的硬件上，并在一个微型系统上，因此它可以被用在PDA和手机上就像笔记本电脑和有线设备上。&lt;/p&gt;&lt;p&gt;蓝牙是个平台不可知的协议，所以java不一定需要使用它。但是java版的蓝牙接口保证在支持java的设备上可以使用它。&lt;/p&gt;&lt;p&gt;使用蓝牙，键盘、鼠标、或者游戏杆不用通过物理线缆连接电脑。这对于桌面系统很好，但是它更大的价值在于便携式电脑上。&lt;/p&gt;&lt;p&gt;类似的，一旦你进入你的汽车，你的耳机就可以和你的手机一起工作，不需要插上插头。同样的耳机可以和你电视或收音机一起工作--任何一个刚好开着的设备。&lt;/p&gt;&lt;p&gt;在商业会议上，蓝牙可以允许你和所有出席的人创建一个ad hoc网络，不用线就可以分享文件、展示幻灯片。在你的办公室，同样的动态构建网络可以通过你的基站提供存取打印机、登陆Inernet，或者同步目录。&lt;/p&gt;&lt;p&gt;蓝牙规范的领导者，Motorola的C. Bala Kumar提出像这样的ad hoc网络同样可以用在买票、在旅馆登记、返还租用的车、或者登记航班。&lt;/p&gt;&lt;p&gt;总之，java蓝牙接口保证允许我们更紧密的联系在一起。&lt;/p&gt;&lt;p&gt;远程客户端加载(Java Web Start)&lt;/p&gt;&lt;p&gt;坦白的说，我很惊讶Java Web Start没有赢得2001 JavaWorld最具创新产品编辑选择奖。Tomcat3.2,拿到了这个也该拿到的奖。但是谈论创新：Java Web Start可以使你的程序拥有打印和I/O能力，这是运行在安全沙盒里的applet所不具有，这将是浏览器不兼容不成为一个问题。这很优雅和很酷。不过在JavaOne上，架构师Rene Schmidt还是列举了这个API的先进功能。&lt;/p&gt;&lt;p&gt;Schmidt展示了将一个应用程序分割成几个jar文件，及使用它们需要的附加库将它们重新联系起来。紧接着他展示了怎么设置一个应用程序描述文件去指定赖加载程序片断，这样用户不用一下下载整个应用程序。&lt;/p&gt;&lt;p&gt;他还指出当程序调用一个功能时，可以使用DownloadService接口。例如：如果帮助系统被调用，程序可以在初始化操作前让DownloadService去得到适合的jar文件。&lt;/p&gt;&lt;p&gt;如果功能已经下载完成，DownloadService当然变成了一个空操作。但是如果jar需要去获取，那么一个默认的进度对话框会提示用户，显示进度条，和提供取消操作。（你可以使用自己定义的对话框，但默认比较简单）。&lt;/p&gt;&lt;p&gt;Schmidt也讲述了创建jardiff文件的过程--jar文件包含递增的更新。他也示范了Java Web Start如何自动下载适合的递增更新，依赖于用户当前安装的版本。&lt;/p&gt;&lt;p&gt;Schmidt讨论了其他功能API的变化，包括文件保存、打开文件、及存取剪切板。操作只在用户接受的情况下执行。在那之后，将来的剪切板存取不出现提示框。换而言之，Java Web Start提供动态的、用户干预的安全管理，不需要用户设置策略文件。&lt;/p&gt;&lt;p&gt;最后，当虚拟机用户选择需要运行的程序，Java Web Start负责下载和安装。这要靠Java Web Start具有一个方便、有效的机制来分发强大的应用程序像部署applet一样简单。&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.javaworld.com/javaworld/jw-06-2001/j1-01-coolapis.html?page=3"&gt;原文链接&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38574248-6634818730579952643?l=zjharry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zjharry.blogspot.com/feeds/6634818730579952643/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38574248&amp;postID=6634818730579952643' title='1 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38574248/posts/default/6634818730579952643'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38574248/posts/default/6634818730579952643'/><link rel='alternate' type='text/html' href='http://zjharry.blogspot.com/2007/03/javacool-apis.html' title='增强了Java的功能的Cool APIs'/><author><name>Harry</name><uri>http://www.blogger.com/profile/14571187675245178578</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38574248.post-3948606308183286193</id><published>2007-03-16T11:14:00.000+08:00</published><updated>2007-03-16T20:27:17.396+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='J2ME'/><category scheme='http://www.blogger.com/atom/ns#' term='PAN'/><category scheme='http://www.blogger.com/atom/ns#' term='蓝牙'/><category scheme='http://www.blogger.com/atom/ns#' term='Bluetooth'/><category scheme='http://www.blogger.com/atom/ns#' term='NetBeans'/><title type='text'>为Java ME程序添加蓝牙文本协议</title><content type='html'>这篇文章的副标题是：学习如何通过蓝牙PAN共享信息和事件。&lt;br /&gt;移动设备在通讯和游戏工业持续的火爆，就像软件倾向于Ad Hoc和点对点网络一样，能处理不同种类设备的能力成为了网络应用程序（不论是游戏、生产还是信息共享）的一个很大优势。在这篇文章中，学习怎样在你的程序中使用和集成蓝牙API（通过JSR82，已经引入了Java 2 平台微型版[j2me]中）。这里，你将会找到完整的蓝牙设备发现，配对，和消息通讯的实现。&lt;br /&gt;&lt;br /&gt;被作为一种创新在移动设备领域持续扩展，及越来越多的公司将芯片集成到他们更多的客户设备上（这不是传统意义上的计算关联），将这些设备连接起来组成一个智能环境的机会在增长。在这篇文章你会看到基于蓝牙Java API的软件包如何使这些设备交换任意的基于文本的消息，以及简单的使用，对于客户端程序有用的API。&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;strong&gt;为什么是蓝牙？&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;蓝牙在构造个人区域网络，低数率连接设备，已经是一项成熟技术，廉价而且是无线的。蓝牙以多种方式（或类型）存在，以适应不同的电源和范围要求。这些特点才使得在移动设备之间和联网的静态设备之间建造Ad Hoc的点对点网络的想法出现，就像消费电子的客厅。&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;strong&gt;为什么使用PANs？&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-size:100%;"&gt;PANs相对于LANs、WANs、和WWW，解决不同问题；PAN的问题通常由方便的方式驱动。多半被技术倾媚的是手机听筒和无键的车辆登录系统。也或者这些解决方案需要蓝牙技术或者其它的无线技术，但倘若提供一个划算的方案，使得比标准的好很多，你就可以进入新市场了。&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;strong&gt;btevent软件包&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-size:100%;"&gt;&lt;/span&gt;要将不同厂家的不同设备连接到一起，你需要一个简单的、灵活的通讯方式。像对象交换技术（OBEX）解决了二进制数据的传输问题，这对于很多蓝牙应用程序是至关紧要的，但没有实现简单的消息协议。同样你需要知道设备和服务发现的概念，对是在设备之间建立Ad Hoc点对点连接的关键。这个brevents包提供一种简单、可重用技术在蓝牙设备之间实现文本通讯。&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;例如，你或许希望你的电视声音在电话响的时候自动调小。代码单1和2展示了如何利用btevents包在客户端程序中开启两个设备之间的通讯，而不需要大量的死板代码。&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;第一个要看的代码是运行在电话上。&lt;/span&gt;&lt;br /&gt;Listing 1. Sample code for a telephone&lt;br /&gt;package bluetooth.livingroom;&lt;br /&gt;import com.ibm.btevents.*;&lt;br /&gt;public class TelephoneMonitor extends MIDlet implements BTEventListener,&lt;br /&gt;PhoneListener {&lt;br /&gt;private BTManager btManager;&lt;br /&gt;public TelephoneMonitor() {&lt;br /&gt;btManager = new BTManager(this);&lt;br /&gt;}&lt;br /&gt;public void incomingCall(PhoneEvent event) {&lt;br /&gt;btManager.sendMessage(&lt;br /&gt;"bluetooth.livingroom.TelevisionMonitor",&lt;br /&gt;"incomingCall:"+event.getCaller()&lt;br /&gt;);&lt;br /&gt;}&lt;br /&gt;public void callEnded(PhoneEvent event) {&lt;br /&gt;btManager.sendMessage(&lt;br /&gt;"bluetooth.livingroom.TelevisionMonitor",&lt;br /&gt;"callEnded:"+event.getDuration()&lt;br /&gt;);&lt;br /&gt;}&lt;br /&gt;public void messageReceived(BTEvent event) {}&lt;br /&gt;public void messageSent(BTEvent event) {}&lt;br /&gt;public void devicesDiscovered(BTEvent event) {}&lt;br /&gt;public void diagnosticMessage(BTEvent event) {}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;TelevisionMonitor类创建一个BTManager对象并注册一个BTEventListner对象。在这个案例中，电话并不关注蓝牙通讯中发生的事件；例如，在TelephoneMonitor中。在这个类中比较有意思的代码在incomingCall() 和callEnded() 方法中。这些方法是被一个虚构的PhoneEvent时间调用的，这样能使TelevisionMonitor 通过BTManager对象传输消息。&lt;br /&gt;&lt;br /&gt;现在，看看另外一边：&lt;br /&gt;Listing 2. Sample code for a television&lt;br /&gt;package bluetooth.livingroom;&lt;br /&gt;import com.ibm.btevents.*;&lt;br /&gt;public class TelevisionMonitor extends MIDlet implements BTEventListener {&lt;br /&gt;private BTManager btManager;&lt;br /&gt;public TelevisionMonitor() {&lt;br /&gt;btManager = new BTManager(this);&lt;br /&gt;}&lt;br /&gt;private void reduceVolume() {&lt;br /&gt;...&lt;br /&gt;}&lt;br /&gt;private void restoreVolume() {&lt;br /&gt;...&lt;br /&gt;}&lt;br /&gt;private void displayMessage() {&lt;br /&gt;...&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public void messageReceived(BTEvent event) {&lt;br /&gt;String message[] = event.getMessage().split(":");&lt;br /&gt;if (message[0].equals("incomingCall")) {&lt;br /&gt;displayMessage("Incoming call from "+message[1]);&lt;br /&gt;reduceVolume();&lt;br /&gt;} else if (message[1].equals("callEnded")) {&lt;br /&gt;displayMessage("Call ended, lasted "+message[1]);&lt;br /&gt;restoreVolume();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public void messageSent(BTEvent event) {}&lt;br /&gt;public void devicesDiscovered(BTEvent event) {}&lt;br /&gt;public void diagnosticMessage(BTEvent event) {}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;这里客户端代码简单的接受消息。如果接收到了一个incomingCall消息，代码减小声音及在屏幕上显示来了个电话。如果接收到callEnded消息，这个代码恢复声音以及显示电话完成。&lt;br /&gt;在上面的每个代码快里，你需要假想关于设备相关的API和事件机制，例如TelephoneMonitor的PhoneEvent对象和TelevisionMonitor在屏幕上显示消息和控制声音的功能。这些功能与设备特性相关，不可能在各种设备上调和。然而，你可以本地实现这些代码；你不需要让电视意识到，或理解PhoneEvents。你只需要设备生产商承认设备代码之间的逻辑链接。在这个案例中，逻辑链接是电视希望知道用户什么时候在打电话。&lt;br /&gt;&lt;br /&gt;接着，看一下brevents如何处理消息。&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;span style="font-size:130%;"&gt;btevents软件包介绍&lt;/span&gt;&lt;/strong&gt;&lt;br /&gt;btevents包是建立在Java蓝牙接口上的。它使得脱离复杂，在不同设备之间，实现一个简单、基于文本的协议。就像名字所暗示的，信息是靠事件间提交的。因为PANs可能是非常动态的，设备在它的范围进入和出去是没有提示的，使用它的所有软件必须遵从异步设计原则以防止暂停核挂起，并通过GUI提示用户。Java语言的事件机制对于这个环境是一个完美的工具。&lt;br /&gt;&lt;br /&gt;Figure 1 展示了btevents包的实现。&lt;br /&gt;&lt;br /&gt;&lt;a name="uml"&gt;Figure 1. Package overview&lt;/a&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;img id="BLOGGER_PHOTO_ID_5042379670459689890" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 374px; CURSOR: hand; HEIGHT: 200px; TEXT-ALIGN: center" height="142" alt="" src="http://bp2.blogger.com/_Qprp0a5njHs/RfohmDhmq6I/AAAAAAAAAAg/36fohErMVmk/s320/uml.jpg" width="393" border="0" /&gt;&lt;strong&gt;&lt;span style="font-size:130%;"&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-size:100%;"&gt;TelephoneMonitor和TelevisionMonitor类都在他们的构造函数中创建了一个BTManager类的实例，因此你应该从研究BTManager类做了什么开始（列表3）。&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a name="listing3"&gt;Listing 3. The BTManager class&lt;/a&gt;&lt;br /&gt;package com.ibm.btevents;&lt;br /&gt;public class BTManager {&lt;br /&gt;private BTTransmitter transmitter;&lt;br /&gt;private BTReceiver receiver;&lt;br /&gt;private BTDiscoverer discoverer;&lt;br /&gt;&lt;br /&gt;public BTManager(BTEventListener listener) {&lt;br /&gt;transmitter = new BTTransmitter();&lt;br /&gt;transmitter.addBTEventListener(listener);&lt;br /&gt;transmitter.start();&lt;br /&gt;receiver = new BTReceiver();&lt;br /&gt;receiver.addBTEventListener(listener);&lt;br /&gt;receiver.start();&lt;br /&gt;discoverer = new BTDiscoverer();&lt;br /&gt;discoverer.addBTEventListener(listener);&lt;br /&gt;discoverer.start();&lt;br /&gt;}&lt;br /&gt;public void startDiscovery() {&lt;br /&gt;discoverer.searchForDevices();&lt;br /&gt;}&lt;br /&gt;public void sendMessage(String remoteName, String message)&lt;br /&gt;throws DeviceNotFoundException {&lt;br /&gt;transmitter.sendMessage(remoteName, message);&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;就像你所看到的，这个类创建和开始3个单独的线程，每个都有个不同的任务。在线程内部实现这些功能，消除了客户端程序在一个链接发送消息是被锁住的可能。&lt;/p&gt;&lt;p&gt;3个线程中的每个都实现了部分使两边能够通讯，就像设备和服务的发现。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;span style="font-size:130%;"&gt;BTDiscoverer&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;现在研究一下BTDiscoverer线程。这个线程允许客户端程序请求本地查找端点，使用BTEvent使得查找结果异步的返回。其中最重要的代码是初始化查找会话：&lt;/p&gt;&lt;p&gt;localDevice.getDiscoveryAgent().startInquiry(DiscoveryAgent.GIAC, this);&lt;/p&gt;&lt;p&gt;这个API调用自身的事件集，需要BTDiscoverer类实现DiscoveryListener接口。为了保持btevents接口干净和兼容，这些事件在内部处理。任何与发现相关的事件需要扩展到BTEvents并通过BTDiscover启动。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;BTReceiver&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;BTReceiver类是使用工作者线程模式设计的服务器，扮演着熟客的角色。它创建一个StreamConnectionNotifier 对象并监听，是否有连接进入。当BTReceiver发现一个连接，就通过StreamConnection对象离开工作者线程去处理输入和发出一个收到消息BTEvent给所有的注册的BTEventListeners。&lt;/p&gt;&lt;p&gt;在两个蓝牙设备之间建立连接，StreamConnection不是唯一的选择。事实上有3种不同的连接方式，如下表&lt;/p&gt;&lt;p&gt;&lt;a name="table1"&gt;Table 1. Types of bluetooth connections&lt;/a&gt;&lt;br /&gt;连接标志 具体名称&lt;/p&gt;&lt;p&gt;btgoep 通用对象交换&lt;br /&gt;btl2cap 逻辑链路和适配层协议&lt;br /&gt;btspp 模拟串口&lt;/p&gt;&lt;p&gt;第一个，btgoep传输二进制数据，所以他不适合基于字符串的通讯。btl2cap需要开发人员做低级的操作，配置最大消息单元。然而，btspp为开发人员隐藏了这些复杂性，因此选择逻辑连接是为了使开发人员的操作简单化。&lt;/p&gt;&lt;p&gt;连接URL通过javax.microedition.io.Connector.open(connURL) 调用的格式：&lt;/p&gt;&lt;p&gt;protected static final String BT_PROTOCOL = "btspp";protected static final String BT_ID = "1234";server = (StreamConnectionNotifier)Connector.open( BT_PROTOCOL + "://localhost:" + BT_ID);&lt;/p&gt;&lt;p&gt;对localhost的引用是很重要的，它告诉open（）去创建一个服务器连接。如果你使用远程地址，你就创建了一个客户端连接。&lt;/p&gt;&lt;p&gt;BTTransmitter&lt;/p&gt;&lt;p&gt;BTTransmitter类，就像名字所暗示的，负责传输消息到远程设备。客户端程序能通过BTManager类提交消息。这是通过BTTransmitter类并添加到一个消息队列。BTTransmitter 线程监控这个队列并使用Connector类发送所有消息。要做到这个，它必须找到远程目标上的服务。这个过程很像设备发现。&lt;/p&gt;&lt;p&gt;localDevice.getDiscoveryAgent().searchServices( null, filter, message.getRemote(), this);&lt;/p&gt;&lt;p&gt;在查找完成后，你才能使用ServiceRecord去创建一个OoutputStream，接着可以写入一个消息：&lt;/p&gt;&lt;p&gt;out = Connector.openOutputStream( record.getConnectionURL(ServiceRecord.NOAUTHENTICATE_NOENCRYPT, false));out.write(message.getMessage().getBytes());fireMessageSentEvent(message.getMessage());&lt;/p&gt;&lt;p&gt;代码发送消息后，他会引发事件到监听器上。&lt;/p&gt;&lt;p&gt;应付PANs不可靠的天性，BTTransmitter线程将有限次重发发送失败的消息。在5次尝试后，就假设设备已经不在范围内了并丢弃消息--这是ad hoc 网络的天性。&lt;/p&gt;&lt;p&gt;使用这个开发包&lt;/p&gt;&lt;p&gt;现在回到感兴趣的工作：使设备相互交谈！你只需要很少的代码，就可以连接设备，运行brevents包。列表4展示了简单的伪代码。&lt;/p&gt;&lt;p&gt;Listing 4. Using the btevents package&lt;br /&gt;import com.ibm.btevents.*;&lt;br /&gt;public class MyBTClass implements BTEventListener {&lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;private BTManager manager;&lt;br /&gt;&lt;br /&gt;public MyBTClass() {&lt;br /&gt;...&lt;br /&gt;manager = new BTManager();&lt;br /&gt;manager.addBTEventListener(this);&lt;br /&gt;...&lt;br /&gt;}&lt;br /&gt;public void messageReceived(BTEvent event) {&lt;br /&gt;...&lt;br /&gt;}&lt;br /&gt;public void messageSent(BTEvent event) {&lt;br /&gt;...&lt;br /&gt;}&lt;br /&gt;public void devicesDiscovered(BTEvent event) {&lt;br /&gt;...&lt;br /&gt;}&lt;br /&gt;public void diagnosticMessage(BTEvent event) {&lt;br /&gt;...&lt;br /&gt;}&lt;br /&gt;public void errorMessage(BTEvent event) {&lt;br /&gt;...&lt;br /&gt;}&lt;br /&gt;}&lt;/p&gt;&lt;p&gt;提供的软件包中包含一个简单的类com.ibm.btevents.ut.BTTestsMIDlet，它实现了一个简单的MIDlet。&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;span style="font-size:130%;"&gt;结论&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;在这篇文章中，你已经知道如何在客户端程序中添加蓝牙传输层而不需要大量的样板代码和考虑异步消息的问题。你可以完成一个清晰的功能，并能使代码开发简单而且可维护。&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www-128.ibm.com/developerworks/wireless/library/wi-javablue/"&gt;原文链接&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38574248-3948606308183286193?l=zjharry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zjharry.blogspot.com/feeds/3948606308183286193/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38574248&amp;postID=3948606308183286193' title='1 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38574248/posts/default/3948606308183286193'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38574248/posts/default/3948606308183286193'/><link rel='alternate' type='text/html' href='http://zjharry.blogspot.com/2007/03/java-me.html' title='为Java ME程序添加蓝牙文本协议'/><author><name>Harry</name><uri>http://www.blogger.com/profile/14571187675245178578</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp2.blogger.com/_Qprp0a5njHs/RfohmDhmq6I/AAAAAAAAAAg/36fohErMVmk/s72-c/uml.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38574248.post-8656584856356632486</id><published>2007-03-14T14:28:00.000+08:00</published><updated>2007-03-14T15:55:44.667+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='键盘'/><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='鼠标'/><category scheme='http://www.blogger.com/atom/ns#' term='NetBeans'/><title type='text'>Java中实现鼠标模拟与键盘映射</title><content type='html'>Java SDK 1.3以后实现了Robot类。此类用于为测试自动化、自运行演示程序和其他需要控制鼠标和键盘的应用程序生成本机系统输入事件。Robot 的主要目的是便于 Java 平台实现自动测试。&lt;br /&gt;使用该类生成输入事件与将事件发送到 AWT 事件队列或 AWT 组件的区别在于：事件是在平台的本机输入队列中生成的。例如，Robot.mouseMove 将实际移动鼠标光标，而不是只生成鼠标移动事件。&lt;br /&gt;Robot中主要的鼠标和键盘控制方法有：&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;void keyPress(int keycode) 按下给定的键。&lt;/li&gt;&lt;li&gt;void keyRelease(int keycode) 释放给定的键。&lt;/li&gt;&lt;li&gt;void mouseMove(int x, int y) 将鼠标指针移动到给定屏幕坐标。&lt;/li&gt;&lt;li&gt;void mousePress(int buttons) 按下一个或多个鼠标按钮。&lt;/li&gt;&lt;li&gt;void mouseRelease(int buttons) 释放一个或多个鼠标按钮。&lt;/li&gt;&lt;li&gt;void mouseWheel(int wheelAmt) 在配有滚轮的鼠标上旋转滚轮。&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;下面就让我们来实战鼠标控制，实现一个简单的鼠标控制程序MouseController。程序功能很简单：随机移动鼠标并点击左键。&lt;/p&gt;&lt;p&gt;代码如下：&lt;/p&gt;&lt;p&gt;import java.awt.AWTException;&lt;/p&gt;&lt;p&gt;import java.awt.Dimension;&lt;/p&gt;&lt;p&gt;import java.awt.Robot;&lt;/p&gt;&lt;p&gt;import java.awt.Toolkit;&lt;/p&gt;&lt;p&gt;import java.awt.event.InputEvent;&lt;/p&gt;&lt;p&gt;import java.util.Random;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;/** &lt;/p&gt;&lt;p&gt;* &lt;/p&gt;&lt;p&gt;* @author Xiaofeng Wang &lt;/p&gt;&lt;p&gt;*/&lt;/p&gt;&lt;p&gt;public class MouseController implements Runnable {&lt;/p&gt;&lt;p&gt;private Dimension dim;&lt;/p&gt;&lt;p&gt;private Random rand; &lt;/p&gt;&lt;p&gt;private Robot robot; &lt;/p&gt;&lt;p&gt;private volatile boolean stop = false; &lt;/p&gt;&lt;p&gt;/** Creates a new instance of Main */ &lt;/p&gt;&lt;p&gt;public MouseController() { &lt;/p&gt;&lt;p&gt;dim = Toolkit.getDefaultToolkit().getScreenSize(); &lt;/p&gt;&lt;p&gt;rand = new Random(); &lt;/p&gt;&lt;p&gt;try { &lt;/p&gt;&lt;p&gt;robot = new Robot(); &lt;/p&gt;&lt;p&gt;} catch (AWTException ex) { &lt;/p&gt;&lt;p&gt;ex.printStackTrace(); &lt;/p&gt;&lt;p&gt;} &lt;/p&gt;&lt;p&gt;}&lt;/p&gt;&lt;p&gt;&lt;br /&gt;public void run() { &lt;/p&gt;&lt;p&gt;while(!stop) { &lt;/p&gt;&lt;p&gt;int x = rand.nextInt(dim.width); &lt;/p&gt;&lt;p&gt;int y = rand.nextInt(dim.height); &lt;/p&gt;&lt;p&gt;robot.mouseMove(x, y); &lt;/p&gt;&lt;p&gt;robot.mousePress(InputEvent.BUTTON1_MASK); &lt;/p&gt;&lt;p&gt;try { &lt;/p&gt;&lt;p&gt;Thread.sleep(3000); &lt;/p&gt;&lt;p&gt;} catch (InterruptedException ex) { &lt;/p&gt;&lt;p&gt;ex.printStackTrace(); &lt;/p&gt;&lt;p&gt;} &lt;/p&gt;&lt;p&gt;} &lt;/p&gt;&lt;p&gt;} &lt;/p&gt;&lt;p&gt;public synchronized void stop() { &lt;/p&gt;&lt;p&gt;stop = true; &lt;/p&gt;&lt;p&gt;} &lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;/** * @param args the command line arguments */ &lt;/p&gt;&lt;p&gt;public static void main(String[] args) { &lt;/p&gt;&lt;p&gt;MouseController mc = new MouseController(); &lt;/p&gt;&lt;p&gt;Thread mcThread = new Thread(mc); &lt;/p&gt;&lt;p&gt;System.out.println("Mouse Controller start"); &lt;/p&gt;&lt;p&gt;mcThread.start(); &lt;/p&gt;&lt;p&gt;try { &lt;/p&gt;&lt;p&gt;Thread.sleep(60000); &lt;/p&gt;&lt;p&gt;} catch (InterruptedException ex) { &lt;/p&gt;&lt;p&gt;ex.printStackTrace(); &lt;/p&gt;&lt;p&gt;} &lt;/p&gt;&lt;p&gt;mc.stop(); &lt;/p&gt;&lt;p&gt;System.out.println("Mouse Controller stoped"); &lt;/p&gt;&lt;p&gt;}&lt;/p&gt;&lt;p&gt;}&lt;/p&gt;&lt;p&gt;当然键盘映射也类似，无非是使用void keyPress(int keycode)。&lt;/p&gt;&lt;p&gt;现在实现了控制鼠标和键盘，接下了我们要获取操作后的效果（屏幕截图）。好在Robot类也提供了一个方法：BufferedImage createScreenCapture(Rectangle screenRect)；可以直接将全屏幕或某个屏幕区域的像素拷贝到一个BufferedImage对象中。&lt;/p&gt;&lt;p&gt;好，下面实战使用robot截屏，实现Capture程序，每隔１秒截屏一次。&lt;/p&gt;&lt;p&gt;代码如下：&lt;/p&gt;&lt;p&gt;public class Capture extends javax.swing.JFrame implements Runnable { &lt;/p&gt;&lt;p&gt;/** Creates new form Capture */ &lt;/p&gt;&lt;p&gt;public Capture() { &lt;/p&gt;&lt;p&gt;initComponents(); &lt;/p&gt;&lt;p&gt;try { &lt;/p&gt;&lt;p&gt;robot = new Robot(); &lt;/p&gt;&lt;p&gt;} catch (AWTException ex) { &lt;/p&gt;&lt;p&gt;ex.printStackTrace(); &lt;/p&gt;&lt;p&gt;} &lt;/p&gt;&lt;p&gt;dim = Toolkit.getDefaultToolkit().getScreenSize(); } &lt;/p&gt;&lt;p&gt;/** This method is called from within the constructor to &lt;/p&gt;&lt;p&gt;* initialize the form. &lt;/p&gt;&lt;p&gt;* WARNING: Do NOT modify this code. The content of this method is &lt;/p&gt;&lt;p&gt;* always regenerated by the Form Editor. &lt;/p&gt;&lt;p&gt;*/ &lt;/p&gt;&lt;p&gt;// &lt;editor-fold defaultstate="collapsed" desc=" 生成的代码 "&gt;&lt;/p&gt;&lt;p&gt;private void initComponents() { &lt;/p&gt;&lt;p&gt;screenCanvas = new java.awt.Canvas();&lt;/p&gt;&lt;p&gt;setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); &lt;/p&gt;&lt;p&gt;stop = true; &lt;/p&gt;&lt;p&gt;setResizable(false);&lt;br /&gt;&lt;/p&gt;&lt;p&gt;javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); &lt;/p&gt;&lt;p&gt;getContentPane().setLayout(layout); &lt;/p&gt;&lt;p&gt;layout.setHorizontalGroup( &lt;/p&gt;&lt;p&gt;layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) &lt;/p&gt;&lt;p&gt;.addComponent(screenCanvas, javax.swing.GroupLayout.PREFERRED_SIZE, 519, javax.swing.GroupLayout.PREFERRED_SIZE) ); &lt;/p&gt;&lt;p&gt;layout.setVerticalGroup( &lt;/p&gt;&lt;p&gt;layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) &lt;/p&gt;&lt;p&gt;.addComponent(screenCanvas, javax.swing.GroupLayout.PREFERRED_SIZE, 434, javax.swing.GroupLayout.PREFERRED_SIZE) &lt;/p&gt;&lt;p&gt;); &lt;/p&gt;&lt;p&gt;pack(); &lt;/p&gt;&lt;p&gt;}// &lt;/EDITOR-FOLD&gt;&lt;/p&gt;&lt;p&gt;/** * @param args the command line arguments */ &lt;/p&gt;&lt;p&gt;public static void main(String args[]) { &lt;/p&gt;&lt;p&gt;final Capture capture = new Capture(); &lt;/p&gt;&lt;p&gt;java.awt.EventQueue.invokeLater(new Runnable() { &lt;/p&gt;&lt;p&gt;public void run() { &lt;/p&gt;&lt;p&gt;capture.setVisible(true); &lt;/p&gt;&lt;p&gt;} &lt;/p&gt;&lt;p&gt;}); &lt;/p&gt;&lt;p&gt;Thread cutThread = new Thread(capture); &lt;/p&gt;&lt;p&gt;cutThread.start(); &lt;/p&gt;&lt;p&gt;} &lt;/p&gt;&lt;p&gt;public void run() { &lt;/p&gt;&lt;p&gt;stop = false; &lt;/p&gt;&lt;p&gt;while(!stop) { &lt;/p&gt;&lt;p&gt;BufferedImage bImage = robot.createScreenCapture(new Rectangle(dim.width, dim.height)); &lt;/p&gt;&lt;p&gt;Graphics g = this.screenCanvas.getGraphics(); &lt;/p&gt;&lt;p&gt;g.drawImage(bImage, 0, 0, this); &lt;/p&gt;&lt;p&gt;try { &lt;/p&gt;&lt;p&gt;Thread.sleep(1000); &lt;/p&gt;&lt;p&gt;} catch (InterruptedException ex) { &lt;/p&gt;&lt;p&gt;ex.printStackTrace(); &lt;/p&gt;&lt;p&gt;} &lt;/p&gt;&lt;p&gt;} &lt;/p&gt;&lt;p&gt;} &lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;private synchronized void stop() { &lt;/p&gt;&lt;p&gt;stop = true; &lt;/p&gt;&lt;p&gt;} &lt;/p&gt;&lt;p&gt;// 变量声明 - 不进行修改 &lt;/p&gt;&lt;p&gt;private java.awt.Canvas screenCanvas; &lt;/p&gt;&lt;p&gt;// 变量声明结束 &lt;/p&gt;&lt;p&gt;private volatile boolean stop; &lt;/p&gt;&lt;p&gt;private Robot robot; &lt;/p&gt;&lt;p&gt;private Dimension dim;&lt;/p&gt;&lt;p&gt;}&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38574248-8656584856356632486?l=zjharry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zjharry.blogspot.com/feeds/8656584856356632486/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38574248&amp;postID=8656584856356632486' title='5 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38574248/posts/default/8656584856356632486'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38574248/posts/default/8656584856356632486'/><link rel='alternate' type='text/html' href='http://zjharry.blogspot.com/2007/03/java_14.html' title='Java中实现鼠标模拟与键盘映射'/><author><name>Harry</name><uri>http://www.blogger.com/profile/14571187675245178578</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38574248.post-9166091322418094886</id><published>2007-03-12T14:03:00.000+08:00</published><updated>2007-03-12T14:39:29.644+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='调试'/><category scheme='http://www.blogger.com/atom/ns#' term='日志'/><category scheme='http://www.blogger.com/atom/ns#' term='NetBeans'/><title type='text'>使用MIDPLogger进行在机调试</title><content type='html'>在进行手机蓝牙远程控制的开发中，需要通过蓝牙控制PC，这个过程无法在模拟器中实现。因此，需要在实际手机上进行调试。比较简单的方式就是通过日志的方式，如下实现：&lt;br /&gt;/*&lt;br /&gt;* GUILogger.java&lt;br /&gt;*&lt;br /&gt;* Created on 2007年2月4日, 上午11:52&lt;br /&gt;*&lt;br /&gt;* To change this template, choose Tools Template Manager&lt;br /&gt;* and open the template in the editor.&lt;br /&gt;*/&lt;br /&gt;package wang.mobile.guanpai;&lt;br /&gt;&lt;br /&gt;import javax.microedition.lcdui.Command;&lt;br /&gt;import javax.microedition.lcdui.CommandListener;&lt;br /&gt;import javax.microedition.lcdui.Displayable;&lt;br /&gt;import javax.microedition.lcdui.Form;&lt;br /&gt;import javax.microedition.midlet.MIDlet;&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt;*&lt;br /&gt;* @author Xiaofeng Wang&lt;br /&gt;*/&lt;br /&gt;public class GUILogger implements CommandListener {&lt;br /&gt;private GuanpaiGame parent;&lt;br /&gt;private Form loggerForm;&lt;br /&gt;private Displayable preForm;&lt;br /&gt;private int level;&lt;br /&gt;&lt;br /&gt;public final static int DEBUG = 0;&lt;br /&gt;public final static int INFO = 1;&lt;br /&gt;&lt;br /&gt;private final Command BACK_CMD = new Command("返回", Command.BACK, 0);&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt;* Creates a new instance of GUILogger&lt;br /&gt;*/&lt;br /&gt;public GUILogger(GuanpaiGame parent, int level) {&lt;br /&gt;this.parent = parent;&lt;br /&gt;this.level = level;&lt;br /&gt;&lt;br /&gt;loggerForm = new Form("跟踪日志");&lt;br /&gt;loggerForm.addCommand(BACK_CMD);&lt;br /&gt;loggerForm.setCommandListener(this);&lt;br /&gt;}&lt;br /&gt;public void setLevel(int level) {&lt;br /&gt;this.level = level;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public synchronized void log(String message, int level) {&lt;br /&gt;if (level &gt;= this.level) {&lt;br /&gt;switch (level) {&lt;br /&gt;case DEBUG:&lt;br /&gt;loggerForm.append("DEBUG：" + message + "\n");&lt;br /&gt;break;&lt;br /&gt;case INFO:&lt;br /&gt;loggerForm.append("INFO：" + message + "\n");&lt;br /&gt;break;&lt;br /&gt;default:&lt;br /&gt;loggerForm.append("未定义的日志类型\n");&lt;br /&gt;break;&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public void showLoggerUI() {&lt;br /&gt;preForm = parent.getDisplay().getCurrent();&lt;br /&gt;parent.getDisplay().setCurrent(loggerForm);&lt;br /&gt;}&lt;br /&gt;public void commandAction(Command command, Displayable displayable) {&lt;br /&gt;if (command == BACK_CMD) {&lt;br /&gt;parent.getDisplay().setCurrent(preForm);&lt;br /&gt;return;&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;看到Series40...上推荐的是&lt;a href="http://www.mobilelandscape.uklinux.net/j2medownload/downloads/MIDPLogger.zip"&gt;MIDPLogger&lt;/a&gt;，别人做好的包，其实自己做个也很简单。&lt;br /&gt;使用也很简单：&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;将文件MIDPLogger，MIDPLogViewer导入你的项目&lt;/li&gt;&lt;li&gt;调用代码如下：&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;// 新建&lt;/p&gt;&lt;p&gt;public class MyMidlet extends MIDlet {&lt;/p&gt;&lt;p&gt;public static MIDPLogger logger;&lt;/p&gt;&lt;p&gt;protected void startApp() {&lt;/p&gt;&lt;p&gt;try {&lt;/p&gt;&lt;p&gt;logger = new MIDPLogger(MIDPLogger.DEBUG, false,true);&lt;/p&gt;&lt;p&gt;}catch(Exception ex) {&lt;/p&gt;&lt;p&gt;ex.printStackTrace();&lt;/p&gt;&lt;p&gt;}&lt;/p&gt;&lt;p&gt;protected void destroyApp(boolean unconditional) {&lt;/p&gt;&lt;p&gt;logger.close();&lt;br /&gt;}&lt;/p&gt;&lt;p&gt;}&lt;br /&gt;&lt;/p&gt;&lt;p&gt;// 记录日志&lt;/p&gt;&lt;p&gt;MyMidlet.logger.write("log message", MIDPLogger.DEBUG);&lt;/p&gt;&lt;p&gt;3. 通过MIDPLogViewer,察看日志。&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38574248-9166091322418094886?l=zjharry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zjharry.blogspot.com/feeds/9166091322418094886/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38574248&amp;postID=9166091322418094886' title='1 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38574248/posts/default/9166091322418094886'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38574248/posts/default/9166091322418094886'/><link rel='alternate' type='text/html' href='http://zjharry.blogspot.com/2007/03/midplogger.html' title='使用MIDPLogger进行在机调试'/><author><name>Harry</name><uri>http://www.blogger.com/profile/14571187675245178578</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38574248.post-7237431983174929393</id><published>2007-03-11T10:34:00.000+08:00</published><updated>2007-03-11T10:53:14.324+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='测试'/><category scheme='http://www.blogger.com/atom/ns#' term='MIDlet'/><category scheme='http://www.blogger.com/atom/ns#' term='NetBeans'/><title type='text'>在测试MIDlet时需要考虑的一些重要方面</title><content type='html'>在测试MIDlet时需要考虑的一些重要方面：&lt;ul&gt;&lt;li&gt;即使运行环境发生改变（如网络连接断开），MIDlet也应该能够正常工作。它应该恰当地处理产生的错误，或者把这些错误用容易理解的消息呈现给用户。&lt;/li&gt;&lt;li&gt;当不再使用网络时，关闭网络连接。&lt;/li&gt;&lt;li&gt;蓝牙设备和服务搜索应该高效的。如果可行，就采用有限查询访问码（LIAC，Limited Inquiry Access Code）来加速搜寻过程。当长时间不使用蓝牙连接时，应该关闭蓝牙连接。&lt;/li&gt;&lt;li&gt;在RMS操作中，当改写重要数据时，就要通知用户。&lt;/li&gt;&lt;li&gt;应用程序的所有主要功能可以轻松地通过主菜单来访问。&lt;/li&gt;&lt;li&gt;每一项功能都像文档中和应用程序的操作说明部分所描述的那样工作。&lt;/li&gt;&lt;li&gt;每个屏幕只在一段时间内显示，这段时间是阅读信息所必需的时间。&lt;/li&gt;&lt;li&gt;需要在整个应用程序中维持以下这些特性的一致性：术语、布局、颜色（或反色）、软键标签、振动和声音。&lt;/li&gt;&lt;li&gt;菜单按逻辑分组，并且菜单结构的分级不能太深。&lt;/li&gt;&lt;li&gt;可以从主菜单中退出应用程序。&lt;/li&gt;&lt;li&gt;软键标签反映了特殊开发人员平台的用户接口的样式。&lt;/li&gt;&lt;li&gt;与右软键相关联的标签指向返回、放弃、退出、取消、清除或其他“否定/后退”的功能。&lt;/li&gt;&lt;li&gt;中间软键只有肯定的功能性命令。&lt;/li&gt;&lt;li&gt;用户下一步最有可能执行的操作（命令的最高优先级）要映射到中间软键。&lt;/li&gt;&lt;li&gt;每个声音都有独特的含义。&lt;/li&gt;&lt;li&gt;声音的设置不能影响应用程序的使用。&lt;/li&gt;&lt;/ul&gt;&lt;p align="right"&gt;--摘自《Series 40 可扩展应用程序开发》&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38574248-7237431983174929393?l=zjharry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zjharry.blogspot.com/feeds/7237431983174929393/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38574248&amp;postID=7237431983174929393' title='1 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38574248/posts/default/7237431983174929393'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38574248/posts/default/7237431983174929393'/><link rel='alternate' type='text/html' href='http://zjharry.blogspot.com/2007/03/midlet_11.html' title='在测试MIDlet时需要考虑的一些重要方面'/><author><name>Harry</name><uri>http://www.blogger.com/profile/14571187675245178578</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38574248.post-2080386173623956296</id><published>2007-03-09T12:18:00.000+08:00</published><updated>2007-03-09T12:22:11.481+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='蓝牙'/><category scheme='http://www.blogger.com/atom/ns#' term='Bluetooth'/><title type='text'>蓝牙技术评介[转]</title><content type='html'>&lt;p&gt;摘要: 本文对蓝牙技术作了扼要介绍,对蓝牙存在问题作了评论。&lt;/p&gt;&lt;p&gt; 一、 蓝牙技术简介&lt;/p&gt;&lt;p&gt;    1、 市场目标"今天的因特网可将全世界的计算机连接起来，明天的蓝牙技术可将全世界的信息家电连接起来"。正是这种人类无穷尽的信息欲，使近年来兴起的蓝牙技术在信息界掀起阵阵热潮，企业界普遍认为，又有一个经济增长热点来临了。&lt;/p&gt;&lt;p&gt;     所谓蓝牙，实际上就是一种短距离(10～100米)的无线连接技术，把一种微型、廉价的通信模块嵌入各类信息设备中，实现这些设备的无线互联，而不用电缆。它可实现语音、数据无线传输及进入网络。它采用全世界统一的开放性规范，使不同厂家的移动电话、计算机、信息家电互联互通成为可能。这些基本要求如能实现，蓝牙产品将会在许多领域得到应用，会有巨大的市场。&lt;/p&gt;&lt;p&gt;以下是蓝牙的几种典型应用：&lt;/p&gt;&lt;p&gt;(1) 产品把手机、笔记本电脑、打印机、电话机、摄像机、投影机等办公设备用无线方式互联互通，成为一个室内移动办公室。&lt;/p&gt;&lt;p&gt;(2) 国际统一标准的蓝牙产品可把手机、电脑与电话网、综合业务网、ADSL、蜂窝移动网等通信网高速连接，可与LAN、WAN、Internet等计算机网互联，实现网上浏览、资源共享及各种电子业务。&lt;/p&gt;&lt;p&gt;(3) 可把彩色电视、音响、灯光控制设备、微波炉、电冰箱、洗衣机等各种信息家电采用不用电缆的无线连接或遥控监视。&lt;/p&gt;&lt;p&gt;     随着蓝牙技术的发展，蓝牙产品不断进入市场，据资料介绍，2000年全球销售为3670万美元，2001年可望达到1.26亿美元，2006年为7亿美元，到2002年可望有1.5亿台信息家电嵌入蓝牙，2005年达到6.7亿台。&lt;/p&gt;&lt;p&gt;2. 发展及现状&lt;/p&gt;&lt;p&gt;环绕建立通用的无线接口、开放性的控制软件两大基本技术目标，蓝牙技术的发展及现状大致如下：&lt;/p&gt;&lt;p&gt;1994年，瑞典Ericsson公司推出蓝牙技术开发计划，其目的是解决移动电话周边设备的无线连接问题。&lt;/p&gt;&lt;p&gt;1997年，Nokia、Intel、IBM和东芝公司加入蓝牙技术开发研究。&lt;/p&gt;&lt;p&gt;1998年，上述五大公司倡导成立蓝牙技术特别兴趣小组，简称SIG。开始系统性研究不需要电缆连接各类信息终端的技术，包括负责制定开放性技术规范，决定专利可向产业界无偿转让。小组成立后，其中有许多是通信、计算机、消费电子产品的知名大企业。蓝牙技术已成为受到工业界广泛支持和关心的技术。全球统一技术规范的原则被确认。&lt;/p&gt;&lt;p&gt;1999年，SIG公布了第一版蓝牙技术规范。&lt;/p&gt;&lt;p&gt;2000年，一些生产手机、计算机的企业宣布它们的一些产品支持蓝牙。如：2000年9月，MOTOROLA公司推出可用于移动电话的蓝牙产品。&lt;/p&gt;&lt;p&gt;同月，东芝美国信息系统公司推出蓝牙PC卡。&lt;/p&gt;&lt;p&gt;同月，MOTOROLA公司宣布它的蓝牙PC卡和USB适配器接受ABI全面认证。&lt;/p&gt;&lt;p&gt;10月，英国Red-M公司推出蓝牙接入服务器，可提供PC机、电话、PDA和WAP实现移动接入，推出第一个蓝牙无线局域网产品。&lt;/p&gt;&lt;p&gt;2000年10月，GCT公司推出第一片蓝牙无线芯片GDM1100。2000年5月，瑞典爱立信公司进行首次蓝牙技术接入系统试验。&lt;/p&gt;&lt;p&gt;2000年10月，Silicom Wave公司宣布它的无线Modem IC第一个得到蓝牙认证。&lt;/p&gt;&lt;p&gt;2001年初，安捷伦、泰瑞达等公司陆续推出可对射频模块与蓝牙芯片进行测试的设备。目前蓝牙部分产品已在许多国家取得了"型号认可"，蓝牙模块目前要用3块芯片，价格为8美元，很快将被压缩为一块芯片，价格降到5美元或更低，企业界希望几年后，手机、PC机、音响、TV、微波炉、电冰箱、灯控设备等信息家电能广泛应用蓝牙技术。&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38574248-2080386173623956296?l=zjharry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zjharry.blogspot.com/feeds/2080386173623956296/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38574248&amp;postID=2080386173623956296' title='2 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38574248/posts/default/2080386173623956296'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38574248/posts/default/2080386173623956296'/><link rel='alternate' type='text/html' href='http://zjharry.blogspot.com/2007/03/blog-post_09.html' title='蓝牙技术评介[转]'/><author><name>Harry</name><uri>http://www.blogger.com/profile/14571187675245178578</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38574248.post-2922827447177193006</id><published>2007-03-07T16:30:00.000+08:00</published><updated>2007-03-07T18:53:11.214+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='单元测试'/><category scheme='http://www.blogger.com/atom/ns#' term='NetBeans'/><title type='text'>注重实效的单元测试总结</title><content type='html'>&lt;p&gt;&lt;strong&gt;一般的原则：&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;测试任何可能失败的地方。&lt;/li&gt;&lt;li&gt;测试任何已经失败的地方。&lt;/li&gt;&lt;li&gt;对于新加的代码，在被证明正确之前，都可能是有问题的。&lt;/li&gt;&lt;li&gt;至少编写和产品代码一样多的测试代码。&lt;/li&gt;&lt;li&gt;针对每次编译都做局部测试。&lt;/li&gt;&lt;li&gt;签入代码之前做全局测试。&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;要回答的问题：&lt;/strong&gt;&lt;/p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;ul&gt;&lt;li&gt;我如何知道代码运行是否正确呢？&lt;/li&gt;&lt;li&gt;我要如何对它进行测试？&lt;/li&gt;&lt;li&gt;还有哪些方面可能会发生错误？&lt;/li&gt;&lt;li&gt;这个问题是否会在其他的地方出现呢？&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;测试哪些方面：使用你的RIGHT-BICEP&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;结果是否正确（Right）？&lt;/li&gt;&lt;li&gt;边界（boundary）条件是否正确？&lt;/li&gt;&lt;li&gt;是否可以检查反向（inverse）关联？&lt;/li&gt;&lt;li&gt;是否可以使用其他方法来交叉检查（cross-check)结果？&lt;/li&gt;&lt;li&gt;错误条件（error condition）是否可以重现？&lt;/li&gt;&lt;li&gt;性能方面是否满足条件？&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;好的测试是A TRIP&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Automatic（自动的）。&lt;/li&gt;&lt;li&gt;Thorough（全面的）。&lt;/li&gt;&lt;li&gt;Repeatable（可重复的）。&lt;/li&gt;&lt;li&gt;Independent（独立的）。&lt;/li&gt;&lt;li&gt;Professional（专业的）。&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;CORRECT边界条件&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;一致性（Conformance)－－值是否符合预期的格式？&lt;/li&gt;&lt;li&gt;有序性（Ordering）－－一组值是该有序的，还是该无序的？&lt;/li&gt;&lt;li&gt;区间性（Range）－－值是否在一个合理的最大值和最小值的范围之内？&lt;/li&gt;&lt;li&gt;引用，耦合性（Reference）－－代码是否引用了一些不受代码本身直接控制的外部因素？&lt;/li&gt;&lt;li&gt;存在性（Existence）－－值是否存在（例如：非null，非零，包含于某个集合等）？&lt;/li&gt;&lt;li&gt;基数性（Cardinality）－－是否恰好有足够的值？&lt;/li&gt;&lt;li&gt;时间性，绝对的或者相对的（Time）－－所有事情是否都是按顺序发生的？是否在正确的时间？是否及时？&lt;/li&gt;&lt;/ul&gt;&lt;p align="right"&gt;&lt;br /&gt;－－摘自《单元测试之道》&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38574248-2922827447177193006?l=zjharry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zjharry.blogspot.com/feeds/2922827447177193006/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38574248&amp;postID=2922827447177193006' title='1 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38574248/posts/default/2922827447177193006'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38574248/posts/default/2922827447177193006'/><link rel='alternate' type='text/html' href='http://zjharry.blogspot.com/2007/03/blog-post.html' title='注重实效的单元测试总结'/><author><name>Harry</name><uri>http://www.blogger.com/profile/14571187675245178578</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38574248.post-6972168895168643472</id><published>2007-03-07T16:22:00.000+08:00</published><updated>2007-03-07T19:09:00.044+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='学习资料'/><category scheme='http://www.blogger.com/atom/ns#' term='NetBeans'/><title type='text'>学习java要经常看的网站[转]</title><content type='html'>&lt;a href="http://java.sun.com/developer/blogs/"&gt;http://java.sun.com/developer/blogs/&lt;/a&gt;--世界是数一数二的JAVA人的BLOG. &lt;a href="http://www.onjava.com/"&gt;http://www.onjava.com&lt;/a&gt; - O'Reilly的Java网站. 每周都有新文章. &lt;a href="http://java.sun.com/"&gt;http://java.sun.com&lt;/a&gt; - 官方的Java开发者网站 - 每周都有新文章发表.&lt;br /&gt;&lt;a href="http://www.developer.com/java"&gt;http://www.developer.com/java&lt;/a&gt; - 由Gamelan.com 维护的Java技术文章网站. &lt;a href="http://www.java.net/"&gt;http://www.java.net&lt;/a&gt; - Sun公司维护的一个Java社区网站.&lt;br /&gt;&lt;a href="http://www.builder.com"&gt;http://www.builder.com&lt;/a&gt; - Cnet的Builder.com网站 - 所有的技术文章, 以Java为主. &lt;a href="http://www.ibm.com/developerworks/java"&gt;http://www.ibm.com/developerworks/java&lt;/a&gt; - IBM的Developerworks技术网站; 这是其中的Java技术主页.&lt;br /&gt;&lt;a href="http://www.javaworld.com/"&gt;http://www.javaworld.com&lt;/a&gt; - 最早的一个Java站点. 每周更新Java技术文章. &lt;a href="http://www.devx.com/java"&gt;http://www.devx.com/java&lt;/a&gt; - DevX维护的一个Java技术文章网站. &lt;a href="http://www.fawcette.com/javapro"&gt;http://www.fawcette.com/javapro&lt;/a&gt; - JavaPro在线杂志网站.&lt;br /&gt;&lt;a href="http://www.sys-con.com/java"&gt;http://www.sys-con.com/java&lt;/a&gt; - Java Developers Journal的在线杂志网站. &lt;a href="http://www.javadesktop.org/"&gt;http://www.javadesktop.org&lt;/a&gt; - 位于Java.net的一个Java桌面技术社区网站. &lt;a href="http://www.theserverside.com/"&gt;http://www.theserverside.com&lt;/a&gt; - 这是一个讨论所有Java服务器端技术的网站. &lt;a href="http://www.jars.com/"&gt;http://www.jars.com&lt;/a&gt; - 提供Java评论服务. 包括各种framework和应用程序. &lt;a href="http://www.jguru.com/"&gt;http://www.jguru.com&lt;/a&gt; - 一个非常棒的采用Q&amp;amp;A形式的Java技术资源社区. &lt;a href="http://www.javaranch.com/"&gt;http://www.javaranch.com&lt;/a&gt; - 一个论坛，得到Java问题答案的地方，初学者的好去处。 &lt;a href="http://www.ibiblio.org/javafaq/javafaq.html"&gt;http://www.ibiblio.org/javafaq/javafaq.html&lt;/a&gt; - comp.lang.java的FAQ站点 - 收集了来自comp.lang.java新闻组的问 题和答案的分类目录.&lt;br /&gt;&lt;a href="http://java.sun.com/docs/books/tutorial/"&gt;http://java.sun.com/docs/books/tutorial/&lt;/a&gt; - 来自SUN公司的官方Java指南 - 对于了解几乎所有的java技术特性非常有帮 助.&lt;br /&gt;&lt;a href="http://www.javablogs.com/"&gt;http://www.javablogs.com&lt;/a&gt; - 互联网上最活跃的一个Java Blog网站.&lt;br /&gt;&lt;a href="http://java.about.com/"&gt;http://java.about.com/&lt;/a&gt; - 来自About.com的Java新闻和技术文章网站.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38574248-6972168895168643472?l=zjharry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zjharry.blogspot.com/feeds/6972168895168643472/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38574248&amp;postID=6972168895168643472' title='2 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38574248/posts/default/6972168895168643472'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38574248/posts/default/6972168895168643472'/><link rel='alternate' type='text/html' href='http://zjharry.blogspot.com/2007/03/java_07.html' title='学习java要经常看的网站[转]'/><author><name>Harry</name><uri>http://www.blogger.com/profile/14571187675245178578</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38574248.post-213526141387070198</id><published>2007-03-06T21:00:00.000+08:00</published><updated>2007-03-07T18:52:31.110+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='多线程'/><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='NetBeans'/><title type='text'>Java多线程编程[转]</title><content type='html'>1.多线程中有主内存和工作内存之分， 在JVM中，有一个主内存，专门负责所有线程共享数据；而每个线程都有他自己私有的工作内存， 主内存和工作内存分贝在JVM的stack区和heap区。&lt;br /&gt;2.线程的状态有`Ready`, `Running`, `Sleeping`, `Blocked`, 和 `Waiting`几个状态，&lt;br /&gt;`Ready` 表示线程正在等待CPU分配允许运行的时间。&lt;br /&gt;3.线程运行次序并不是按照我们创建他们时的顺序来运行的，CPU处理线程的顺序是不确定的，如果需要确定，那么必须手工介入，使用setPriority()方法设置优先级。&lt;br /&gt;4.我们无从知道一个线程什么时候运行，两个或多个线程在访问同一个资源时，需要synchronized&lt;br /&gt;5. 每个线程会注册自己，实际某处存在着对它的引用，因此，垃圾回收机制对它就“束手无策”了。&lt;br /&gt;6. Daemon线程区别一般线程之处是：主程序一旦结束，Daemon线程就会结束。&lt;br /&gt;7. 一个对象中的所有synchronized方法都共享一把锁，这把锁能够防止多个方法对通用内存同时进行的写操作。synchronized static方法可在一个类范围内被相互间锁定起来。&lt;br /&gt;8. 对于访问某个关键共享资源的所有方法，都必须把它们设为synchronized，否则就不能正常工作。&lt;br /&gt;9. 假设已知一个方法不会造成冲突，最明智的方法是不要使用synchronized，能提高些性能。&lt;br /&gt;10. 如果一个"同步"方法修改了一个变量，而我们的方法要用到这个变量(可能是只读),最好将自己的这个方法也设为 synchronized。&lt;br /&gt;11. synchronized不能继承，　父类的方法是synchronized，那么其子类重载方法中就不会继承“同步”。&lt;br /&gt;12. 线程堵塞Blocked有几个原因造成：&lt;br /&gt;(1)线程在等候一些IO操作&lt;br /&gt;(2)线程试图调用另外一个对象的“同步”方法，但那个对象处于锁定状态，暂时无法使用。&lt;br /&gt;13.原子型操作(atomic), 对原始型变量(primitive)的操作是原子型的atomic. 意味着这些操作是线程安全的， 但是大部分情况下，我们并不能正确使用，来看看 i = i + 1 , i是int型，属于原始型变量：&lt;br /&gt;(1)从主内存中读取i值到本地内存.&lt;br /&gt;(2)将值从本地内存装载到线程工作拷贝中.&lt;br /&gt;(3)装载变量1.&lt;br /&gt;(4)将i 加 1.&lt;br /&gt;(5)将结果给变量i.&lt;br /&gt;(6)将i保存到线程本地工作拷贝中.&lt;br /&gt;(7)写回主内存.&lt;br /&gt;注意原子型操作只限于第1步到第2步的读取以及第6到第7步的写, i的值还是可能被同时执行i=i+1的多线程中断打扰(在第4步)。&lt;br /&gt;double 和long 变量是非原子型的(non-atomic)。数组是object 非原子型。&lt;br /&gt;14. 由于13条的原因，我们解决办法是：&lt;br /&gt;class xxx extends Thread{&lt;br /&gt;//i会被经常修改&lt;br /&gt;private int i;&lt;br /&gt;public synchronized int read(){ return i;}&lt;br /&gt;public synchronized void update(){ i = i + 1;}&lt;br /&gt;..........&lt;br /&gt;}&lt;br /&gt;15. Volatile变量， volatile变量表示保证它必须是与主内存保持一致，它实际是"变量的同步", 也就是说对于volatile变量的操作是原子型的，如用在long 或 double变量前。&lt;br /&gt;16. 使用yield()会自动放弃CPU，有时比sleep更能提升性能。&lt;br /&gt;17. sleep()和wait()的区别是：wait()方法被调用时会解除锁定，但是我们能使用它的地方只是在一个同步的方法或代码块内。&lt;br /&gt;18. 通过制造缩小同步范围，尽可能的实现代码块同步，wait(毫秒数)可在指定的毫秒数可退出wait；对于wait()需要被notisfy()或notifyAll()踢醒。&lt;br /&gt;19. 构造两个线程之间实时通信的方法分几步：&lt;br /&gt;(1). 创建一个PipedWriter和一个PipedReader和它们之间的管道;&lt;br /&gt;PipedReader in = new PipedReader(new PipedWriter())&lt;br /&gt;(2). 在需要发送信息的线程开始之前，将外部的PipedWriter导向给其内部的Writer实例out&lt;br /&gt;(3). 在需要接受信息的线程开始之前，将外部的PipedReader导向给其内部的Reader实例in&lt;br /&gt;(4). 这样放入out的所有东西度可从in中提取出来。&lt;br /&gt;20. synchronized带来的问题除性能有所下降外，最大的缺点是会带来死锁DeadLock，只有通过谨慎设计来防止死锁，其他毫无办法，这也是线程难以驯服的一个原因。不要再使用stop() suspend() resume()和destory()方法&lt;br /&gt;21. 在大量线程被堵塞时，最高优先级的线程先运行。但是不表示低级别线程不会运行，运行概率小而已。&lt;br /&gt;22. 线程组的主要优点是：使用单个命令可完成对整个线程组的操作。很少需要用到线程组。&lt;br /&gt;23. 从以下几个方面提升多线程的性能：&lt;br /&gt;检查所有可能Block的地方，尽可能的多的使用sleep或yield()以及wait();&lt;br /&gt;尽可能延长sleep(毫秒数)的时间;&lt;br /&gt;运行的线程不用超过100个，不能太多；&lt;br /&gt;不同平台linux或windows以及不同JVM运行性能差别很大。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38574248-213526141387070198?l=zjharry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zjharry.blogspot.com/feeds/213526141387070198/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38574248&amp;postID=213526141387070198' title='1 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38574248/posts/default/213526141387070198'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38574248/posts/default/213526141387070198'/><link rel='alternate' type='text/html' href='http://zjharry.blogspot.com/2007/03/java.html' title='Java多线程编程[转]'/><author><name>Harry</name><uri>http://www.blogger.com/profile/14571187675245178578</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38574248.post-8890042605366926936</id><published>2007-03-06T20:27:00.000+08:00</published><updated>2007-03-07T18:51:56.903+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='事件模型'/><category scheme='http://www.blogger.com/atom/ns#' term='MIDlet'/><category scheme='http://www.blogger.com/atom/ns#' term='lcdui'/><category scheme='http://www.blogger.com/atom/ns#' term='NetBeans'/><title type='text'>MIDlet的事件模型</title><content type='html'>javax.mircoedition.lcdui包实现了一个同时运行在高级API和低级API上的事件模型。它处理诸如用户交互之类的事件并请求重绘屏幕。当触发一个事件时，事件模型获得通知并通过相应的回调使MIDlet相应事件。一共有4种类型的UI事件：&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;表示抽象命令的事件，作为高级API的一部分；&lt;/li&gt;&lt;li&gt;表示按下或释放某个键的低级事件，或拥有鼠标的设备的鼠标事件；&lt;/li&gt;&lt;li&gt;调用Canvas类的paint()方法的事件，可以通过一个repaint()调用产生；&lt;/li&gt;&lt;li&gt;通过调用Display类的callSerially()来请求调用一个Runnable对象的run()方法。&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;所有的回调都是串行的，决不会并行执行。更确切地说，一个新的回调决不会在另一个回调正在运行的时候启动。下一个回调仅在前一个执行完毕后才会启动，即使在有一系列的事件需要处理的时候也是如此，不管是谁在何处使用，甚至一个事件回调方法本身就是调用者。&lt;/p&gt;&lt;p&gt;抽象命令(abstract commands)仅仅通过语义上定义，用于避免不得不实现实际的命令按钮。Command(命令按钮)被附加在Displayable对象上，如高级的List或Form对象，或低级的Canvas对象。addCommand()方法添加一个Command到Displayable对象上。Command指定了标签、类型和优先级。CommandListener则实现了实际的命令处理。设备的本地风格可以决定哪些Command出现在UI的什么位置。例如，"Exit"总是被放置在Nokia设备的右软键上方。&lt;/p&gt;&lt;p&gt;还有一些设备提供的操作能帮助操作一些高级API。例如，屏幕对象如List和ChoiceGroup有内键的事件能返回用户输入并交应用程序处理。&lt;/p&gt;&lt;p align="right"&gt;—摘自《Symbian OS J2ME编程指南》&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38574248-8890042605366926936?l=zjharry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zjharry.blogspot.com/feeds/8890042605366926936/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38574248&amp;postID=8890042605366926936' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38574248/posts/default/8890042605366926936'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38574248/posts/default/8890042605366926936'/><link rel='alternate' type='text/html' href='http://zjharry.blogspot.com/2007/03/midlet.html' title='MIDlet的事件模型'/><author><name>Harry</name><uri>http://www.blogger.com/profile/14571187675245178578</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38574248.post-2904243619782529358</id><published>2007-02-15T19:42:00.000+08:00</published><updated>2007-02-15T19:50:51.317+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='模板'/><title type='text'>关于c++模板</title><content type='html'>&lt;ul&gt;&lt;li&gt;通常而言，并不是把模板编译成一个可以处理任何类型的单一实体；而是对于实力化模板参数的每种类型，都从模板产生出一个不同的实体。&lt;/li&gt;&lt;li&gt;用具体类型代替参数的过程叫实例化（instantiation）。&lt;/li&gt;&lt;li&gt;模板被编译了两次：&lt;/li&gt;&lt;/ul&gt;&lt;ol&gt;&lt;li&gt;实例化之前，先检查模板代码本身，查看语法是否正确；在这里发现错误的语法，如遗漏分号等。&lt;/li&gt;&lt;li&gt;实例化期间，检查模板代码，查看是否所有的调用都有效。在这里会发现无效的调用，如该实例化类型不支持某些函数调用等。&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38574248-2904243619782529358?l=zjharry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zjharry.blogspot.com/feeds/2904243619782529358/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38574248&amp;postID=2904243619782529358' title='1 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38574248/posts/default/2904243619782529358'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38574248/posts/default/2904243619782529358'/><link rel='alternate' type='text/html' href='http://zjharry.blogspot.com/2007/02/c_15.html' title='关于c++模板'/><author><name>Harry</name><uri>http://www.blogger.com/profile/14571187675245178578</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38574248.post-2354781518050947474</id><published>2007-02-15T19:33:00.000+08:00</published><updated>2007-02-15T19:39:03.083+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c语言'/><category scheme='http://www.blogger.com/atom/ns#' term='struct'/><title type='text'>struct在c程序中的应用</title><content type='html'>struct在c程序中的应用如下：&lt;br /&gt;&lt;ol&gt;&lt;li&gt;将一般作为一个整体来使用的数据元素集合在一起；&lt;/li&gt;&lt;li&gt;从函数返回多个数据元素；&lt;/li&gt;&lt;li&gt;构造链式数据结构；&lt;/li&gt;&lt;li&gt;映射数据在硬件设备、网络链接和存储介质上的组织方式；&lt;/li&gt;&lt;li&gt;实现抽象数据类型；&lt;/li&gt;&lt;li&gt;以面向对象的方式编程。&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38574248-2354781518050947474?l=zjharry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zjharry.blogspot.com/feeds/2354781518050947474/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38574248&amp;postID=2354781518050947474' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38574248/posts/default/2354781518050947474'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38574248/posts/default/2354781518050947474'/><link rel='alternate' type='text/html' href='http://zjharry.blogspot.com/2007/02/structc.html' title='struct在c程序中的应用'/><author><name>Harry</name><uri>http://www.blogger.com/profile/14571187675245178578</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38574248.post-3537544047631327122</id><published>2007-02-14T20:43:00.000+08:00</published><updated>2007-02-14T20:48:30.342+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='blog'/><category scheme='http://www.blogger.com/atom/ns#' term='笔记'/><category scheme='http://www.blogger.com/atom/ns#' term='note'/><title type='text'>我的笔记</title><content type='html'>整理房间翻出了一些笔记，打算把原来的汗水，整理到blog上。&lt;br /&gt;上面是第一篇，敬请关注。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38574248-3537544047631327122?l=zjharry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zjharry.blogspot.com/feeds/3537544047631327122/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38574248&amp;postID=3537544047631327122' title='1 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38574248/posts/default/3537544047631327122'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38574248/posts/default/3537544047631327122'/><link rel='alternate' type='text/html' href='http://zjharry.blogspot.com/2007/02/blog-post.html' title='我的笔记'/><author><name>Harry</name><uri>http://www.blogger.com/profile/14571187675245178578</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38574248.post-1866079721081307183</id><published>2007-02-14T20:37:00.000+08:00</published><updated>2007-02-14T20:50:09.480+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='指针'/><category scheme='http://www.blogger.com/atom/ns#' term='c语言'/><title type='text'>在c程序中，指针一般用途</title><content type='html'>&lt;p&gt;在c程序中，指针一般用来：&lt;/p&gt;&lt;ol&gt;&lt;li&gt;构造链式数据结构&lt;/li&gt;&lt;li&gt;引用动态分配的结构&lt;/li&gt;&lt;li&gt;实现引用调用（Call by reference）（避免复制的开销）&lt;/li&gt;&lt;li&gt;访问和迭代数据元素&lt;/li&gt;&lt;li&gt;传递数组参数&lt;/li&gt;&lt;li&gt;引用函数&lt;/li&gt;&lt;li&gt;作为其它值的别名&lt;/li&gt;&lt;li&gt;代表字符串&lt;/li&gt;&lt;li&gt;直接访问系统内存&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38574248-1866079721081307183?l=zjharry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zjharry.blogspot.com/feeds/1866079721081307183/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38574248&amp;postID=1866079721081307183' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38574248/posts/default/1866079721081307183'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38574248/posts/default/1866079721081307183'/><link rel='alternate' type='text/html' href='http://zjharry.blogspot.com/2007/02/c.html' title='在c程序中，指针一般用途'/><author><name>Harry</name><uri>http://www.blogger.com/profile/14571187675245178578</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38574248.post-116955812414126553</id><published>2007-01-23T21:10:00.000+08:00</published><updated>2007-03-07T18:51:15.928+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='jni'/><category scheme='http://www.blogger.com/atom/ns#' term='NetBeans'/><title type='text'>在windows下使用Netbeans开发Java JNI程序</title><content type='html'>&lt;p&gt;我选择的开发工具链是JDK1.6 Netbeans5.5 Netbeans-mobility-5.5 Netbeans-cnd-5_5-windows Sun_java_wireless_toolkit-2_5-beta2-windows 如下&lt;br /&gt;这篇主要是实战在netbeans下的Java JNI程序开发。&lt;br /&gt;&lt;strong&gt;为什么JNI重要&lt;/strong&gt;&lt;br /&gt;在java中直接访问硬件驱动，操作系统的接口就必须通过JNI方式。&lt;br /&gt;&lt;strong&gt;本实践中需要的软件有:&lt;br /&gt;&lt;/strong&gt;J2SE Development Kit (JDK™) 6.0 (&lt;a href="http://java.sun.com/javase/downloads/index.jsp"&gt;download&lt;/a&gt;)&lt;/p&gt;&lt;p&gt;NetBeans IDE 5.5 (&lt;a href="http://www.netbeans.org/downloads/index.html" target="_blank"&gt;download&lt;/a&gt;)&lt;br /&gt;NetBeans C/C++ Pack 5.5 (&lt;a href="http://www.netbeans.org/downloads/index.html" target="_blank"&gt;download&lt;/a&gt;)&lt;br /&gt;Cygwin (&lt;a href="http://www.cygwin.com/" target="_blank"&gt;download&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;开始实战:&lt;/strong&gt;&lt;br /&gt;1. &lt;strong&gt;安装Cygwin&lt;/strong&gt;&lt;br /&gt;Cygwin程序作用是在windows平台上模拟一个unix shell环境，让gcc等unix工具能在windows上运行。&lt;br /&gt;进入Cygwin安装包选择界面时选择gcc-core， gcc-g++， gdb，make这几项(所要依赖的程序包Cygwin程序会自动选中的)。如图下:&lt;br /&gt;对了，还要配置一下环境变量，让命令行能找cygwin的程序。把cygwin的bin目录放入系统path中就OK了。&lt;br /&gt;&lt;br /&gt;2. &lt;strong&gt;在Netbean中新建一个java application&lt;/strong&gt;，如：JavaJNIDemo。&lt;br /&gt;内容可以如下：&lt;br /&gt;/**&lt;br /&gt;*&lt;br /&gt;* @author Xiaofeng Wang&lt;br /&gt;*/&lt;br /&gt;public class Main {&lt;br /&gt;public native int addTwoNumbers(int one， int two);&lt;br /&gt;public native int multiplyTwoNumbers(int one， int two);&lt;br /&gt;&lt;br /&gt;static {&lt;br /&gt;System.load("D:\\NetBeans\\JNIDynamicLibraryDemo\\dist\\JNIDynamicLibraryDemo。dll");//动态链接库的位置&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/** Creates a new instance of Main */&lt;br /&gt;public Main() {&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt;* @param args the command line arguments&lt;br /&gt;*/&lt;br /&gt;public static void main(String[] args) {&lt;br /&gt;Main main = new Main();&lt;br /&gt;int num1 = 20;&lt;br /&gt;int num2 = 50;&lt;br /&gt;&lt;br /&gt;System.out.println(num1 + " + " + num2 + " = " + main。addTwoNumbers(num1， num2));&lt;br /&gt;System.out.println(num1 + " * " + num2 + " = " + main。multiplyTwoNumbers(num1， num2));&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;3. &lt;strong&gt;接着要生成头文件&lt;/strong&gt;&lt;br /&gt;在命令行中用javah程序生成上面java文件的头文件。&lt;br /&gt;命令格式如下：&lt;br /&gt;javah -o d:\ JNIDemoNative.h –jni -classpath &lt;projects_root&gt;\JavaJNIDemo\build\classes javajnidemo.Main&lt;br /&gt;完成后在D盘根目录下会找到JNIDemoNative。h文件，内容如下:&lt;br /&gt;/* DO NOT EDIT THIS FILE - it is machine generated */&lt;br /&gt;#include &lt;jni。h&gt;&lt;br /&gt;/* Header for class javajnidemo_Main */&lt;br /&gt;&lt;br /&gt;#ifndef _Included_javajnidemo_Main&lt;br /&gt;#define _Included_javajnidemo_Main&lt;br /&gt;#ifdef __cplusplus&lt;br /&gt;extern "C" {&lt;br /&gt;#endif&lt;br /&gt;/*&lt;br /&gt;* Class: javajnidemo_Main&lt;br /&gt;* Method: addTwoNumbers&lt;br /&gt;* Signature: (II)I&lt;br /&gt;*/&lt;br /&gt;JNIEXPORT jint JNICALL Java_javajnidemo_Main_addTwoNumbers&lt;br /&gt;(JNIEnv *， jobject， jint， jint);&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;* Class: javajnidemo_Main&lt;br /&gt;* Method: multiplyTwoNumbers&lt;br /&gt;* Signature: (II)I&lt;br /&gt;*/&lt;br /&gt;JNIEXPORT jint JNICALL Java_javajnidemo_Main_multiplyTwoNumbers&lt;br /&gt;(JNIEnv *， jobject， jint， jint);&lt;br /&gt;&lt;br /&gt;#ifdef __cplusplus&lt;br /&gt;}&lt;br /&gt;#endif&lt;br /&gt;#endif&lt;br /&gt;&lt;br /&gt;4. &lt;strong&gt;安装配置NetBeans C/C++ Pack 5.5插件&lt;br /&gt;&lt;/strong&gt;安装完NetBeans C/C++ Pack 5.5插件后，新建一个C/C++项目（如：JNIDynamicLibraryDemo），并配置项目属性如下：&lt;br /&gt;还要配置编译参数：&lt;br /&gt;内容为-mno-cygwin -Wl，--add-stdcall-alias -shared -m32&lt;br /&gt;-mno-cygwin 让编译出来的DLL不依赖cygwin&lt;br /&gt;-Wl，--add-stdcall-alias 不使用此参数会出现链接错误&lt;br /&gt;-shared 生成动态库&lt;br /&gt;-m32 编译为32位程序&lt;br /&gt;&lt;br /&gt;还要配置dll的输出名称（如：JNIDynamicLibraryDemo。dll）&lt;br /&gt;&lt;br /&gt;把上一步中生成的头文件导入到项目中，并新建JNIDynamicLibraryDemo。c文件，内容如下：&lt;br /&gt;#include "JNIDemoNative。h"&lt;br /&gt;&lt;br /&gt;JNIEXPORT jint JNICALL Java_javajnidemo_Main_addTwoNumbers(JNIEnv * env， jobject obj， jint one， jint two) {&lt;br /&gt;return (one + two);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;JNIEXPORT jint JNICALL Java_javajnidemo_Main_multiplyTwoNumbers(JNIEnv * env， jobject obj， jint one， jint two) {&lt;br /&gt;return (one * two);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;5. &lt;strong&gt;编译并运行项目&lt;/strong&gt;&lt;br /&gt;编译c项目，并输出dll，核对java项目中dll的路径是否正确，如正确运行项目。结果如下：&lt;br /&gt;到此完成。&lt;br /&gt;&lt;br /&gt;参考资料：&lt;br /&gt;&lt;a href="http://www.netbeans.org/kb/55/beginning-jni-part1.html"&gt;Beginning JNI with NetBeans™ C/C++ Pack 5。5&lt;/a&gt;&lt;br /&gt;《Java高级编程：JDK5》&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38574248-116955812414126553?l=zjharry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zjharry.blogspot.com/feeds/116955812414126553/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38574248&amp;postID=116955812414126553' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38574248/posts/default/116955812414126553'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38574248/posts/default/116955812414126553'/><link rel='alternate' type='text/html' href='http://zjharry.blogspot.com/2007/01/windowsnetbeansjava-jni.html' title='在windows下使用Netbeans开发Java JNI程序'/><author><name>Harry</name><uri>http://www.blogger.com/profile/14571187675245178578</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38574248.post-116955450980757179</id><published>2007-01-23T20:10:00.000+08:00</published><updated>2007-02-14T20:55:37.634+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='毕业设计'/><title type='text'>毕业设计</title><content type='html'>现在毕业设计的题目定下来了，我也要忙了。一直很期待毕业设计，想把它做成什么什么样。现在看来当初的想法有点天真。在短短的几个月内，凭个人的精力是没法完成什么了不起的项目的。但想想了不起项目并不是一开始就不得了：就像Unix刚开始是为了利用一台旧电脑而开发的, bell实验室根本没有把它作为一个项目来看待,后来才看到它的巨大价值。Oracle刚出来的时候bug很多，经常会挂掉，而现在的Oracle被称为能买得到的最好的商用数据库……软件也像人一样是个成长过程的。&lt;br /&gt;我的毕业设计中主要用到J2ME,蓝牙、Java桌面编程、JNI编程、Socket编程，也要涉及到调用windows的系统API。其中有些我比较熟悉了，也有没尝试过的。&lt;br /&gt;对比较陌生的技术，最好先尝试一下，免得以后卡在那里。用老师的话也就是先把它走通。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38574248-116955450980757179?l=zjharry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zjharry.blogspot.com/feeds/116955450980757179/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38574248&amp;postID=116955450980757179' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38574248/posts/default/116955450980757179'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38574248/posts/default/116955450980757179'/><link rel='alternate' type='text/html' href='http://zjharry.blogspot.com/2007/01/unix-belloraclebugoracle.html' title='毕业设计'/><author><name>Harry</name><uri>http://www.blogger.com/profile/14571187675245178578</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-38574248.post-116955416229764266</id><published>2007-01-23T20:03:00.000+08:00</published><updated>2007-03-07T19:11:56.079+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='blog'/><title type='text'>开始写blog</title><content type='html'>经常去逛别人的blog，现在自己也写写吧。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/38574248-116955416229764266?l=zjharry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zjharry.blogspot.com/feeds/116955416229764266/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=38574248&amp;postID=116955416229764266' title='3 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/38574248/posts/default/116955416229764266'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/38574248/posts/default/116955416229764266'/><link rel='alternate' type='text/html' href='http://zjharry.blogspot.com/2007/01/blog.html' title='开始写blog'/><author><name>Harry</name><uri>http://www.blogger.com/profile/14571187675245178578</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry></feed>
