2006年1月2日
#
Java 8之前,同一注解不能在相同的目标元素上多次使用,例如,如下的注解在Java 8之前是不允许的:
public class SampleClass {
@Quality("Security")
@Quality("Performance")
@Quality("Readability")
public void foo(){
//
}
}
Java 8引入了Repeatable注解(@Repeatable)可以解决这一问题,但光有可重复的注解定义还不够,还需要它的容器注解,两者一起来实现可重复注解的使用。实例如下:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
@Repeatable (Qualities.class)
public @interface Quality {
String value();
}
@Target(ElementType.METHOD)
public @interface Qualities {
Quality[] value();
}
其中,Quality是可重复注解,由@Repeatable注解标明,它的容器注解是Qualities,用于存放所有可重复的Quality(存贮在Quality[]中);同时还要注意可重复注解和它的容器注解的目标元素必须是一样的(这也不言自明)。如此这般,我们最开始的
SampleClass 在Java 8环境下就可以安全使用了。
以下单例实现思想来自《Java Design Patterns: A Programmer's Approach》.
该方法利用了Java缺省的Lazy类实例化机制克服了传统单例模式实现中Lazy实例化方式的不足。
public class Singleton {
private Singleton(){}
public static Singleton getInstance(){
return Helper.instance;
}
static class Helper {
private static Singleton instance = new Singleton();
}
}
以下转自StackOverflow(
http://stackoverflow.com/questions/5074063/maven-error-failure-to-transfer),亲测可用。
This worked for me in Windows as well.
- Locate the {user}/.m2/repository (Using Juno /Win7 here)
- In the Search field in upper right of window, type ".lastupdated". Windows will look through all subfolders for these files in the directory. (I did not look through cache.)
- Remove them by Right-click > Delete (I kept all of the lastupdated.properties).
- Then go back into Eclipse, Right-click on the project and select Maven > Update Project. I selected to "Force Update of Snapshots/Releases". Click Ok and the dependencies finally resolved correctly.
当我们写Groovy脚本代码的时候,有时会发生编译错误,如下:
- Groovy:Invalid duplicate class definition of class XXX : The source XXXX\XXX.groovy contains at least two
definitions of the class XXX.
- The type XXX is already defined
原因在于Groovy会把.groovy代码文件作为脚本或类定义来处理,例如如下代码:
class Order {
def security
def value
private buy_sell(su, closure) {
security = su[0]
quantity = su[1]
closure()
}
def getTo() {
this
}
}
def methodMissing(String name, args) {
order.metaClass.getMetaProperty(name).setProperty(order, args)
}
def getNewOrder() {
order = new Order()
}
Integer.metaClass.getShares = { -> delegate }
Groovy会把上述代码作为脚本处理,同时缺省用文件名来作为一个外围类类包括整个脚本程序,此时,如果该文件名恰好也是Order的话,那么就会出现重复的类定义错误提示。
解决办法是将脚本文件名取另外一个不同的名字。
已经申请OCUP中级考试的学员可以在一年内(截止到17年9月份)免费申请OCUP2中级考试的资格(原有考试仍可以参加)。此外,2014年3月份之后参加了原有OCUP中级认证考试的学员可以免费申请OCUP2中级认证考试。详见OMG网站声明(http://www.omg.org/ocup-2/exam-info.htm)。
搬家总是难免的,但旧家的东西不能带走难免会留下些许遗憾,希望它们能永远留下来.......
欢迎光临我的新家:
http://blog.sciencenet.cn/?53016 (科学网)
转自网络。
3岁,他去上幼儿园了,看着他小小的坚强的背影,心中又喜悦又有点小小的心酸。离别了一整天,孩子看到你高兴得奔跑过来,扑在你的怀里。跟你说:妈妈,我想你了。那一刻,抱着孩子就像抱着了整个世界。
6岁,他上小学了,孩子终于走进校门,这是多么值得纪念的事情,孩子的人生从此翻开了新的篇章,却没想到,这也是孩子离开我们的第一步。他已经对与你分开一天习以为常了,而且他喜欢每天去学校,这是他更喜欢的生活。甚至,他有时还会说:妈妈,在家好无聊,没有小朋友和我玩。
12岁,他上初中了,甚至有的开始上寄宿学校,一个月或者几个月回一次家,见上一次面。他们开始不再依赖你,甚至,他们喜欢和你对着干。你想帮他们做点事情,他们说:妈妈,我自己来吧。突然觉得这句话让我们觉得好失落,孩子是不是不再需要我们了?
18岁,他离开你去上大学,一年回来两次。回来的好几天前,家里的冰箱就装不下了,为他准备了各种各样他喜欢吃的东西。可是一回来打个照面,他就忙着和同学朋友聚会去了。从此,你最怕听到的一句话是:妈妈,我不回家吃饭了,你们自己吃吧。
大学毕业后,孩子留在了远方工作,一年也难的回来一次了。好不容易回来一趟,几天就走了。你最盼望的就是孩子的电话,希望,孩子对你说一声:妈妈,我很好,你保重身体。这样就足够了。
孩子结婚了,回家的时间有一半匀给了你的亲家,孩子回来的更少了。你已经习惯就老两口在家了,但是,你最希望听到孩子对你说:妈妈,今年过年我回家过啊!
当孩子又有了他们自己的孩子,你已经不再是他们的家庭成员了,他们的一家三口(或一家n口)里,已经不包括你们了。
而我们也慢慢的习惯了这样的日子。只是习惯在闲来无事的时候,经常翻翻相册,看看我们自己的一家三口,无论孩子身在何方,他却永远是我们家庭中无可取代的一员。
是啊,其实当孩子在身边的日子,我们是多么幸福。可是有时我们却还会抱怨。抱怨因为他,你做了太多的牺牲。抱怨他晚上老醒来,让你睡不好,抱怨他无理取闹,抱怨他爱撒娇长不大,抱怨他生病,让你操碎了心,抱怨为了培养他,花费了太多的精力与金钱...可是,如果你想想,10多年后,就算你想要,也没有机会了。孩子会不停的长大,过了这个时期他就再没有这个时期的习性。你是不是常常在他断奶后怀念喂他吃奶的日子,可是那时你却觉得好累好辛苦好厌倦。是不是常常看他以前吃手的照片觉得好可爱,可是你曾经却为要不停的给他洗手而烦恼透了。是不是在他褪去童声后,特别想念他曾经奶声奶气的声音,可是他以前撒娇的时候你却很不受用。是不是当孩子去上学后你特别怀念他黏在你身边的日子,可是以前你却总在想他要什么时候才能去上学啊。。。
时间无法倒流,过去了就只能永远过去了。孩子能呆在身边的日子是多么难得与宝贵。因为这一点,我更加的珍惜与孩子相处的每一刻,也让我无论遇到什么,都心存感恩。谢谢上天给我这么一个孩子,让我分享与见证他成长的每一刻。无论带给我多少困难,烦恼,甚至挫败,无论让我失去多少睡眠,时间,金钱,精力,我仍然豁达,因为,这都是上天的恩赐。
当他在身边的每一天,我都会让他觉得幸福,也是让我们都有一个美好的回忆。我不会给他太多压力,束缚,更不会给他牵绊,阻扰,但是我会适时管教,也会做量力而行的投资,因为我有责任与义务教会他生活的本领,好让他来日自由快乐的飞翔。同时,我也会告诉他,就算所有的路都行不通时,还有一条路你可以畅行,那就是回家的路。。。。。。。。
今日编辑一PDF文件(用的是Adobe Acrobat Pressional 7.0),删除了几页,然后保存,结果文件大小反而增加了;而删除几页后另存,则文件大小减少。
你也试试看。
Robert L. Glass在《Negative Productivity and What to Do about It》(详见IEEE Software, September/October 2008, p. 96)阐述了自己对那些影响项目进度的人的亲身感受和对此应采取的解决方案。
作者以个体差异开头(作者指出,在软件工程文献中提到过非常大的个体差异:28:1 (for error identification) to 25:1 (for coding ability) to 11:1 (for timing efficiency) to 6:1 (for sizing efficiency)。但不幸的是,这些差异并没有得到我们足够的认识,作为实践者,我们不知道如何鉴别出那些是别人28倍生产力的人,他们对于按时交付高质量的软件非常重要;作为研究者,在案例研究中也没有对个人进行足够的区分,这将导致对结果的误读。),然后引出对项目进展带来负作用(影响项目进度)的人''(someone who has negative productivity—that is, someone whose inclusion on a project actually makes the project less efficient.)'',接着以自己的亲身经历的三个例子做了阐述:
1. Disfunctional labor relations. 项目(与软件无关)组被抽走一人,却发现生产力提高了;这个案例让作者意识到项目中存在让人不易觉察的对项目生产力产生负影响的人;
2. Moral rebellion. 作者所带领的项目组中存在一个对公司存在性不认同的人,导致项目进度滞后,使作者受到了软件职业中最差的评价;
3. Overly high standards. 作者所在的项目组由于一个对质量要求非常严的QA,总是对提交的产品不满意,结果导致产品迟迟不能交付。
对待这些人,作者给出了自己的解决方案:解雇他们。''(If someone on your project is deliberately delaying its progress, there’s probably only one reasonable solution. Fire them! If you don’t, your team will be sorry, your company will be sorry, and, quite likely, you’ll be sorry as well!)''
第九届全国软件与应用学术会议(NASAC 2010)如期(11.4~11.7)在苏州大学举行,对于本次会议,有以下几点感受:
1. 学术水平有待提高(投稿主体还是以硕士生为主,尚不能吸引国内高水平文章);
2. 学术交流有待提高(本次会议的很多短文都未准备Poster,演示和茶歇的环境很有限);
3. 会议招待有待提高(除了欢迎宴以外,就都是自助了,很单一,应该多样化一些);欢迎晚宴很一般,由于专委没有参加,所以缺少了很多交互,没有节目,没有致辞,就是一味的吃
本次会议的收获是认识了一些同行,并与北大和复旦的相关研究人员就软件复用和产品线相关实践以及企业应用实践的相关问题进行了讨论。还有就是吃到了正宗的阳澄湖大闸蟹(一公一母)。
苏州风光很好,游览了一些古街,小桥流水,无限柔美,但环境保护还有待加强,经常可以看到吸烟的把烟头从湖水中扔,还有吐痰的......,要是苏州在国外,一定会更美。
9.13至9.17日,第十四届国际软件产品线会议
(SPLC 2010)在韩国济州岛的
华美达酒店举行。这是SPLC第二次来到亚洲(上次是2007年在日本。作为软件工程知名会议,SPLC轮流在美洲、亚洲和欧洲举行,是系统化软件复用的专业会议)。
作为与工业界联系比较紧密、体现软件工业化的主流会议,SPLC 2010并未得到国内的关注,这在一定程度上体现了国内工业界的相对落后的局面(既没有产品线的实践,又缺乏对先进软件生产方式的跟踪与研究)。
本次的参会者来自国内的只有 5 人(包括我和导师,分别来自北京大学、上海交通大学、东北大学和公安部第一研究所)当然也有一些海外华人(老师和在读的博士(后))。会议论文集收录了来自国内的一篇短文、一篇Poster(我们的),以及一篇工业化论文。对我来讲,最大的收获在于开阔了视野、了解了一些当前最新进展和认识结交了一些新朋友,当然,这也是我第一次出国,虽然离家很近。
值得一提的是,来自公安部第一研究所的李东老师参加了
Software Product Line Fame of Hall竞评演讲(本次会议唯一的一个),至于能否加入Fame of Hall要等下次会议(SPLC 2011,慕尼黑)才能知晓,不过李老师所展示的航空安检系统产品线已经得到了与会绝大多数人员(好像没有发现几个不赞成的,呵呵)的认可,很可能成为国内第一家啊,祝福。
去年10月份向《计算机工程》投了一篇稿件,审稿加修改共耗时2个月,然后被录用,说安排在今年11月左右发表,结果今年10月份就发表了,本来是件好事,但我注意到的一个重要问题是文章中刊出的“收稿时间”竟然是今年的5月份,我很惊讶,于是给编辑部留言问是怎么回事,但始终没有人答复。
如此大的时间差别(去年10月份到今年5月份那可是7个月之久啊),难道是编辑“手误”,手误也应该做个解释啊,怎么就是不回留言呢。之前我也注意到一些发表的论文(10月份之前发表的)中刊出的“收稿时间”大概也在今年的2,3月份,当时我还想怎么这么多在我之后收稿的却在我之前发表呢,看来这也许是一种故意行为,“潜规则”!!!
难道出版社就为了显示自己发表周期短欺骗广大科研工作者吗?先不说这本身就是学术不端,重要的是它直接给投稿者带来了巨大的风险——剽窃。试想一篇思想类似的文章如果是在去年10分之后投稿如果发表了(当然前提是其它期刊刊出的收稿时间是真实的),那会是什么情况??不用说别人肯定认为是我剽窃,所以收稿时间应该是绝对真实的,我想这也是这个信息在文章中出现的主要价值!!!!。另外的小问题就是给投稿者的工作量/绩效统计带来不便,明明是去年的工作量怎么体现的是今年的时间,万一领导复查,怎么说清楚呢。
结论,再也不向此刊投稿了。
转自InfoQ:http://www.infoq.com/cn/news/2009/09/study-multitasking-performance
----------------------------------------------------------------------------------------------------------
斯坦福大学上个月在Proceedings of the National Academy of Sciences学报上发布了一个研究结果:“媒体行业中多工人员(multitasker)的认知控制”,强调指出一个显而易见的事实:从效率的角度考虑同时从事多任务,绝对会影响工作效率。该研究审视了IT领域中一个广为人知、却常常为人忽略的现象:不断出现、正在发生的多任务工作方式。敏捷实施者们这样写:这下可算有理由让团队只开发一个产品了,而且只能有一个产品负责人——将时间花在多个任务之上绝对是效率低下的工作方式。
Wired杂志指出:虽然其他研究重点关注多任务工作方式的眼前效果(比如:办公室里的工作人员经常检查邮件,这种情况下的工作效率),该研究提出了一个不同寻常的问题:“要是人们总在使用多任务工作方式会怎么样?”Stanford的研究者Clifford Nass、Anthony Wagner和Eyal Ophir调查了262名学生的媒体消费习惯。19名使用多任务方式最多的学生和22名多任务方式最少的学生此后参加了两个电脑测试,集中精力完成手上的测试。
他们使用了一些标准的心理测试指标,研究结果显示出:经常在多个信息流之间转换的学生,他们会在e-mail、网页、视频、聊天和电话之间来回切换,他们取得的进展远低于不怎么采取多任务方式的学生。更令研究人员惊讶的是:在任务切换能力的测试上,“重度媒体多任务人士”表现更差,“似乎他们过滤不相干任务的干扰的能力更差。”
该研究再次强调了认知科学家反复提到的事情:同时处理多个信息流的输入被认为是人类认知能力的问题。
对于造成差异的原因——被定位使用多任务方式的人是不是先存在心智上的不健全,还是说多任务方式造成了这种情况——“这是一个需要投入上百万美金才能回答的问题,可是我们没有一百万美金去取得答案。”Ness这么说。
Wagner接下来打算用脑部造影方法来研究多任务方式的神经学解释,而Ness将会研究儿童人群在多任务习惯上的发展。
本文是对:
Linda Wilbanks. IT Productivity = ??. IT Pro, November/December 2009, pp. 64, 63
的总结。
文章探讨了什么事生产效率(或工作效率,但并没有深入,只是个引子),以及如何提高(员工)的工作效率。
文章开头指出,“productivity”(生产力,此处译为工作效率)通常被定义为生产效能(efficiency)、度量(metrics),以及在生产过程中单位输入得到的产出的衡量。但对IT人员来说,什么是生产效能呢?作者给出了一个非正式的定义“一个有效率的人是指那些能够在指定的时间内以高质量的方式完成指定工作的人。”这引出下一个问题:我们如何做可以使员工更有效率?
作者援引Mr. Elgan在2009年4月5号的Computerworld那期中的一篇文章“Why Goofing Off at Work Boots Productivity"中的话说,
那些偷偷在Fackbook和Twitter上花少量时间的办公室“懒鬼”(slacker)比那些全部时间都用来做工作的人能做更多的工作。墨尔本大学的研究人员在一项新的研究中证实了这种真实性。他们的研究发现,一般来说,那些为了个人原因在工作时间内使用Internet的人比不用的人效率高9%。
作者指出,尽管Mr. Elgan没有指出这些研究者是如何衡量生产率的,但他给出了为什么那些在Internet上花费时间的人更具有效率的一些原因:
- 潜意识仍然关注于工作中的问题,解决方案通常会在随后出现;
- “游手好闲”(Goof off)的时间是一段清理个人思想、消除个人顾虑的时间。在这一小段时间后,你会回来全身心的投入到工作中;
- 从项目或任务中的短暂休息也可能是在受教育(或学习),例如读一些与工作无关的东西。这些信息有可能在以后帮你解决另外的问题。
作者接着列举了一些管理者们在不鼓励计算机游戏或网络冲浪的情况下建议所采用的提高员工效率的方式:
- 给员工有意义的工作。
- 承认/赏识员工所完成的工作。
- 给员工为了最好完成工作所需要的工具。
- 批准员工休息。
- 给予员工尊重。
作者还举了一个例子,说有个复有创造力的同事把键盘上的F1~F12都附加了新功能:
F1 Accurately reflect what’s in the building’s vending machines.
- F2 Display the current traffic report for the area.
- F3 Make every piece of software on your machine work exactly as advertised.
- F4 Play your favorite music to lower your blood pressure.
- F5 Bring up your favorite picture of the beach or of the place you plan to retire.
- F6 Show a running clock on how many hours you have left until you retire.
- F7 Show you where your kids or pets are (but be careful, this might not relieve stress!).
- F8 Automatically delete all emails that were sent “Reply All.”
- F9 Delete all meetings for the day, sending emails of regret to all attendees.
- F10 Show what your 401K balance was two years ago instead of today’s value.
- F11 Automatically start dinner/ESPN/CNN/soap opera (programmable to suit individual preferences).
- F12 Advance time to five minutes before quitting time on Friday of the current week.
作者最后指出,作为管理者,需要关注如何现实的鼓励员工发挥他们最大的效率,还需要决定如何来优化工作环境。只要求生产效而没有适当的管理支持和资源将适得其反。作者认为,不时地准备一块蛋糕(不管什么原因)可以鼓励团队和沟通。
By the way:作者是美国能源部国家核安全管理局的CIO。
转自:http://www.sciencenet.cn/m/user_content.aspx?id=275801
1个民工>2院院士
话说我国一特大型国有企业B从A国引进了一条香皂包装生产线,结果发现这条生产线有个致命缺陷:常常会有盒子里没装入香皂。总不能把空盒子卖给顾客啊。没办法,B企业向国务院S部打报告,S部指定两院和C9高校联合设计一个方案来分拣空的香皂盒,于是组成了一个11人的科研团队,计有:中科院院士1人、中国工程院院士1人、北京大学863首席科学家1人、清华大学973首席科学家1人、上海交通大学长江学者1人、浙江大学国家重点实验室主任1人、复旦大学“国家杰青”1人、南京大学国贴专家1人、哈尔滨工业大学国家大科学工程主任1人、中国科技大学引智计划1人,当中有海龟、陆龟、土鳖,还有博士后、博士、硕士、本科生,综合采用了机械、微电子、自动化、x射线探测、微机编程等技术,花了100万元,成功解决了问题。每当生产线上有空香皂盒通过,两旁的探测器会检测到,并且驱动一只机械手把空皂盒推走。
南方有个乡镇企业也买了同样的生产线,四川老板发现这个问题后大为发火,找了个湖南的小工来说:你他妈的今天给老子把这个搞定,不然明天你给老子滚蛋......小工很快想出了办法:他在生产线旁边放了台风扇猛吹,空皂盒自然会被吹走。
这个故事告诉我们:
1,知识不一定就是生产力,创造力和学历、学识、学衔不直接相关。
2,能吹是多么的重要,院士也能吹出来。
3,民科是值得尊重的,应该与官科享受同等待遇。
4,再次证明人民的智慧是无穷的,历史是群众创造的,是普通的劳动人民创造的。
本文是对Steve Vinoski. Multilanguage Programming.
IEEE Internet Computing, Vol. 12, No. 3, MAY/JUNE 2008, pp. 83-85 的总结。
本文的主要观点是:在软件开发中,要为特定的任务选择最合适的开发语言。
作者首先介绍了在软件集成和软件开发中涉及的术语/技术浩如烟海,但是开发者却只坚持某种技术,而必须使用其它技术来解决问题。这种现象在开发语言领域也是一样。开发者总是使用自己喜欢的语言,而非解决问题最优的语言,会造成设计方案的不优。
作者指出在日常开发中了解和使用多种编程语言可以带来显著的好处,因为没有任何一门语言适用于解决所有问题。而语言的存在也主要是由于它适于解决某些特定方面的问题(在解决某些问题方面比其它语言好),因此,不断有语言出现和消亡。在编程语言设计和开发中涉及许多需要权衡的因素,因此,这为许多不同的方案和变体预留了空间。
作者指出,大部分单一语言开发者倾向选择用于通用目的的语言(像Java、C++等),而不是特定的编程语言。通用的编程语言可用于解决更广范围的问题,但它们通常都是提供的折中的解决方案,不是太好,也不是太坏。当然,一些单一语言开发者尽力去挖掘语言的高级特性,来将语言的能力发挥到极致,但这些程序员仍然受制于这门语言实际的限度。
作者指出语言的选择对开发效率是一个重要因素,选择正确的语言所带来的开发效率的提升是巨大和值得这么去做的。作者以对XML的处理为例阐述了此观点。通用语言,例如Java在处理XML方面没有专门设计上的支持,这使得开发人员在使用通用语言处理XML方面忍受这种不匹配,来进行拙笨的开发,造成非优的解决方案。在这种情况下,为了提高效率,他们通常采用一些代码生成技术,把XML构造块影射为静态编程语言的构造块(通常是类)来尽量缓解这种阻抗,即便如此,这种方式仍然是十分脆弱的。因为把高度灵活的XML构造块转化为严格的静态的数据类型很容易造成彼此版本的不匹配。XML文档的任何改变都需要新的代码生成、重新构建、....这使得通过代码生成获得的一点点好处又被不断维护带来的成本所抵消。相比之下,Python、Perl、Erlang等语言都提供了XML处理模块,甚至还带版本化功能。更好的像ECMAscript for XML (E4X)和Scala,提供了对XML字面量的支持支持,开发人员可以直接在语言语法中写XML。消除了阻抗,带来了更简化的代码和更清晰的功能。
作者指出,选择适当的语言所带来的效率的提升还体现在对代码的维护上。作者援引Fred Brooks在《人月神话》中引用的的研究发现说,所需开发和维护的工作量与指令的数目(可以理解为代码行)是指数关系,而且这与所采用的语言无关。假设这个指数值是1.5的话,那么如果代码行是原来的3倍的话,那么就需要5倍的开发和维护成本,如果代码行变为原来的5倍,就需要11倍的开发和维护成本,如果代码行变为原来的10倍,那么就需要32倍的开发和维护成本。选择正确的语言,不仅可以减少代码行,更快的提供解决方案和对需要的响应,这个过程可以变为积极的循环,更少的代码带来更好的缺陷和更容易的增强(维护),这又使得用户更高兴,提供免费的广告宣传和反馈,进一步促进软件的发展。
作者指出,多语言编程的一个问题就是如何使它们协同工作。这可以分为两类。如果是用于分布式应用集成(即不同的应用用不同的语言),那么网络本身就通过协议提供了一个中立的方案,可以通过网络消息等。如果不是分布式应用,当前的主流开发语言,比如微软的CLT(公共语言运行时)所支持的语言越来越多,命令式的、动态的、函数式的,或脚本的。类似的,JVM也从一个单语言平台演化为一个可以支持许多语言的平台,包括JRuby、Scala、Groovy、JavaScript、E4X、Jython和其它的。而且,在JVM上,这些语言都容易学,因为都是基于字节码,这些语言可以与Java进行互调。因此,JVM提供了一个非常好的方式来为应用的不同部分选择最适合的语言。
作者还指出目前阻碍多语言编程的因素主要有两个:一个管理因素;另一个开发者认为学习新语言难度很大。对于第一个因素,管理者通常认为只采用一种语言易于管理,因为大家都用同样的语言,可以容易的替换开发人员,而且某个开发人员写的代码,大家也都能看懂,避免陷入只有少数人才能看懂和维护的局面。作者认为这种管理者对软件开发和维护所涉及的成本没有充分考虑。在一个JVM或CLR基础之上,选择合适的语言可以减少代码规模和开发维护的工作量,从而降低系统的总成本,而且,较小的系统需要更少的开发者,这又是一个巨大的成本减少。对于第二个因素,相比通用语言来说,那个特定的语言,像Lisp、Python等都很简练,核心概念并不多,初学者可以很快发现它们更具有生产力,而且,以往语言的经验可以帮助你学习新语言。如果你掌握的语言越多,你就能更容易的学习一门新语言,也能发现解决问题的最好方式。
最后,作者以“毕竟,难道我们真的认为我们已经学到我们所需要的最后一门(终极)语言了码?”结尾。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
欢迎您对自己所在的开发组织对于多语言编程、融合的实践和经验发表看法,谢谢!
今天是部门年会活动的日子,活动项目:滑雪、年夜饭、卡啦OK
第一次学滑雪,是挺兴奋的,11点钟开使滑,地点林海滑雪场,刚开始是50多米的小短坡, Easy,吃完午饭,开始在200米的高坡滑,跟头栽了不老少,也是长了不少经验。爽!,就是膝盖太累了...
晚上又是一顿丰盛大餐....
1. 提供了磁盘分区 - 空间方法
在File类中增加了以下方法:
public long getFreeSpace(): 返回一个分区剩余空间
public long getTotalSpace(): 返回一个分区总空间
public long getUsableSpace(): 返回一个分区已用空间
注意,以上File指代的虚拟路径必须是盘符,否则返回0。
2. Splash Screen
Mustang对于Splash Screen的实现是一个用来显示gif(可以是动画式的),PNG, jpg图片的没有修饰的窗口
使用方式:
在java命令行中加入 -splash 选项,示例如下:
java -splash mypic.jpg HelloWorld如果你的类是以jar的方式来运行,那么可以在jar文件的MANIFEST.MF文件中加入如下的一行:
SplashScreen-Image:mypic.jpg你也可以在命令行中写:
java -splash:mypic.jpg -jar helloWorld.jar
这里用的图片将替代MANIFESET.MF中定义的图片(如果有的话)
为了实现自定义的Splash Screen界面,你可以使用如下的方法:
//使用SplashScreen的静态方法获得SplashScreen对象,然后自定义
SplashScreen ss = SplashScreen.getSplashScreen ();
if (ss != null)
{
// 自定义代码。
}
在SpalshScreen中还提供了如下方法,具体使用请看JDK或访问sun网站
public Graphics getGraphics()
public URL getImageURL()
public Dimension getSize()
public void setImageURL(URL imageURL):
public void update()
值得注意的是:你必须使用 -spalsh选项或MANIFEST.MF的方式来调用SplashScreen,
否则修改是无效的。
昨晚,回到宿舍,正好赶上中央4套在播《名将之约》,这次邀请的名将是现任中国乒乓球队总教练,刘国梁。
自己小时候就很喜欢乒乓球,到现在也是一样,因此对于此类人物,自己是钦佩有加,更何况刘的辉煌战绩,在国内也是先有人出其右。本月十号,就是他三十岁的生日,以近而立之年的他,已经是中国乒乓球的总教练,让人感觉前途不可限量,要登上这个高度是非常之不易。
今年,我也已经27啦,时光飞逝,转眼就会到30岁的那一天,作为程序员这个行当中的一员,这个年龄虽然不是很大,但绝对不小,自己的明天在哪里?
30岁能达到什么高度?35,40呢?也许每一个IT人都会思考这个问题,当然也许有些牛人已经是扶摇直上九万里,不必忧心此类问题。
我们的公司很大,部门也很多,好几千人的规模,项目经理很多很多,而公司级的项目经理,也就是资深项目经理,再加上部门的领导,什么技术总监,项目总监,部长,经理......
人,只有踏踏实实的把他目前的工作做好,才能不断提升自己,我从不怀疑这样的真理。
今天又抖出这个老生常谈的话题,一是有感而发,再则警示自己:抛弃浮躁,潜心修行。
Oracle ADF(Application Developement Framework)是一套快速开发企业级J2EE的MVC框架. Oracle在Model层和业务服务层上提供的缺省实现对开发基于数据库的应用提供了极大的便利,尤其是它的ADF BC(Business components),这个微型的MVC框架提供了直接映射数据库表的能力,结合View端的展现(Oracle 提供了桌面端Swing/JClient和Web端UIX的实现),开发起来就如同用Borland的数据感知控件一样。
Spring目前是J2EE社区一个比较火的框架,应用的比较广,那如何进行二者的有机结合呢?
我们已经习惯了Spring的IOC框架,方便的使用getBean()方法来获得我们想要的对象,因此,如果能通过Spring来生成需要的对象,然后把这个对象注册为Data Control(Oracle中数据感知组件),这样就可以利用ADF BC的威力来快速构建一个数据库应用。问题的关键就在于ADF为每一个data control指定了一个工厂类属性,而这个工厂类属性的实例值需要我们用Spring来生成,就OK了。举一个实际的例子:
在Spring中,我们定义了如下的接口:
package nl.amis.spring.hrm;
import java.util.List;
public interface HrmService {
public void setEmployeeDao(EmpDAO employeeDAO);
public List getAllEmployees();
public long getSalarySum();
}
配置文件为:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="dataSourceDBDirect"
class="org.springframework.jdbc.datasource.DriverManagerDataSource"
destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:@localhost:1521:orcl"/>
<property name="username" value="scott"/>
<property name="password" value="tiger"/>
</bean>
<bean id="employeeDAO" class="nl.amis.spring.jdbc.EmployeeJdbcDAO">
<property name="dataSource">
<ref local="dataSourceDBDirect"/>
</property>
</bean>
<bean id="hrmService" class="nl.amis.spring.hrm.HrmServiceImpl">
<property name="employeeDao">
<ref local="employeeDAO"/>
</property>
</bean>
</beans>
在Oracle JDeveloper开发环境下,我们找到
nl.amis.spring.hrmServiceImp这个类,然后用菜单命令把它注册为一个Data control组件。这个新生成的Data control缺省名字是:HrmServiceImplDataControl,查看它的属性,有一个Factory class属性,找到这个属性所指的类,修改如下源码:
Object bean = oracle.jbo.common.JBOClass.forName(beanClass).newInstance();上面的代码就是生成HrmServiceImpl对象的代码,把它改为:
ApplicationContext springCtx = new ClassPathXmlApplicationContext("SpringConfig.xml");
Object bean = springCtx.getBean("hrmService");这样主要工作就OK啦,剩下的就是修改一下Data Control的配置文件(在注册成为Data Control后生成的同名.xml文件),修改
<content>中的<AccessorAtribute>部分,把id改为:allEmployees; BeanClass 改为nl.amis.spring.hrm.Employee; IsCollection="true"; Type改为java.Util.List.
以上修改表明我们需要的是通过employeeDao获得的Employee的集合,把这个结合作为结果集应用到ADF BC中。
英文原文出自:
http://technology.amis.nl/blog/index.php?p=765
要调用的Web服务是求两个整数和,并返回结果。
服务的WSDL文件内容如下:
<?xml version="1.0" encoding="utf-8" ?>
<wsdl:definitions
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:s="http://www.w3.org/2001/XMLSchema"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:tns="http://tempuri.org/"
xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
targetNamespace="http://tempuri.org/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
<wsdl:types>
<s:schema elementFormDefault="qualified"
targetNamespace="http://tempuri.org/">
<s:element name="AddTwoIntegers">
<s:complexType>
<s:sequence>
<s:elementminOccurs="1" maxOccurs="1" name="IntegerOne" type="s:int" />
<s:elementminOccurs="1" maxOccurs="1" name="IntegerTwo" type="s:int" />
</s:sequence>
</s:complexType>
</s:element>
<s:element name="AddTwoIntegersResponse">
<s:complexType>
<s:sequence>
<s:elementminOccurs="1" maxOccurs="1" name="AddTwoIntegersResult" type="s:int" />
</s:sequence>
</s:complexType>
</s:element>
</s:schema>
</wsdl:types>
<wsdl:message name="AddTwoIntegersSoapIn">
<wsdl:part name="parameters" element="tns:AddTwoIntegers" />
</wsdl:message>
<wsdl:message name="AddTwoIntegersSoapOut">
<wsdl:part name="parameters" element="tns:AddTwoIntegersResponse" />
</wsdl:message>
<wsdl:portType name="SimpleServiceSoap">
<wsdl:operation name="AddTwoIntegers">
<wsdl:input message="tns:AddTwoIntegersSoapIn" />
<wsdl:output message="tns:AddTwoIntegersSoapOut" />
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="SimpleServiceSoap" type="tns:SimpleServiceSoap">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" />
<wsdl:operation name="AddTwoIntegers">
<soap:operation soapAction="http://tempuri.org/AddTwoIntegers" style="document" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="SimpleService">
<documentation xmlns="http://schemas.xmlsoap.org/wsdl/" />
<wsdl:port name="SimpleServiceSoap" binding="tns:SimpleServiceSoap">
<soap:address location="http://localhost/Develop.NET/Home.Develop.WebServices/SimpleService.asmx"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
javaScript代码中利用了MS的HTTP代理对象XMLHTTP,在Mozilla's Web brower中相应的组件是XMLHttpRequest,他们都提供了类似的方法来完成soap请求。下面的代码用的是IE中的XMLHTTP对象。代码假定调用过程中没有Fault。
function fncAddTwoIntegers(a, b)
{
var oXmlHttp = new ActiveXObject("MSXML2.XMLHTTP");
oXmlHttp.open("POST", "http://localhost/Develop.NET/Home.Develop.WebServices/SimpleService.asmx'", false);
oXmlHttp.setRequestHeader("Content-Type", "text/xml");
oXmlHttp.setRequestHeader("SOAPAction", "http://tempuri.org/AddTwoIntegers");
oXmlHttp.send("
<soap:Envelopexmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xmlns:xsd='http://www.w3.org/2001/XMLSchema'
xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'>
<soap:Body>
<AddTwoIntegersxmlns='http://tempuri.org/'>
<IntegerOne>" + a + "</IntegerOne>
<IntegerTwo>" + b + "</IntegerTwo>
</AddTwoIntegers>
</soap:Body>
</soap:Envelope>");
return oXmlHttp.responseXML.selectSingleNode("//AddTwoIntegersResult").text;
}
原文英文出自:
http://builder.com.com/5100-6371_14-5887775.html?tag=nl.e601
Document方式是Web service缺省调用模式,和literal相组合,给我们调用Web service提供了极大的便利,省去了RPC调用方式的复杂类型序列化的问题,所以,Doucment调用方式在BPEL领域应用非常广泛,下面介绍基于Axis利用Document方式来调用一个Web service.
1. Web service准备:
Web service你可以任意实现一个,我是利用Oracle BPEL,通过建立一个BPEL流程,然后把它发布为Web service(具体创建过程省略),这里重要的是Web service的WSDL文件,这是我们调用的门户。
下面是我的Web service的WSDL文件内容:
<definitions
name="HelloWorld"
targetNamespace="http://xmlns.oracle.com/HelloWorld"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:plnk="http://schemas.xmlsoap.org/ws/2003/05/partner-link/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:client="http://xmlns.oracle.com/HelloWorld"
>
<types>
<schema attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://xmlns.oracle.com/HelloWorld"
xmlns="http://www.w3.org/2001/XMLSchema">
<element name="HelloWorldProcessRequest">
<complexType>
<sequence>
<element name="input" type="string"/>
</sequence>
</complexType>
</element>
<element name="HelloWorldProcessResponse">
<complexType>
<sequence>
<element name="result" type="string"/>
</sequence>
</complexType>
</element>
</schema>
</types>
<message name="HelloWorldRequestMessage">
<part name="payload" element="client:HelloWorldProcessRequest"/>
</message>
<message name="HelloWorldResponseMessage">
<part name="payload" element="client:HelloWorldProcessResponse"/>
</message>
<portType name="HelloWorld">
<operation name="process">
<input message="client:HelloWorldRequestMessage"/>
<output message="client:HelloWorldResponseMessage"/>
</operation>
</portType>
<binding name="HelloWorldBinding" type="client:HelloWorld">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="process">
<soap:operation style="document" soapAction="process"/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
</binding>
<service name="HelloWorld">
<port name="HelloWorldPort" binding="client:HelloWorldBinding">
<soap:address location="http://robin:9700/orabpel/default/HelloWorld/1.0"/>
</port>
</service>
<plnk:partnerLinkType name="HelloWorld">
<plnk:role name="HelloWorldProvider">
<plnk:portType name="client:HelloWorld"/>
</plnk:role>
</plnk:partnerLinkType>
</definitions>
2. 编写调用类,代码如下:
import java.net.MalformedURLException;
import java.net.URL;
import java.rmi.RemoteException;
import java.util.Vector;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.rpc.ServiceException;
import org.apache.axis.client.Call;
import org.apache.axis.constants.Style;
import org.apache.axis.message.SOAPBodyElement;
import org.apache.xml.serialize.DOMSerializerImpl;
import org.apache.xml.serialize.OutputFormat;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
public class BPELServiceTest {
//service的命名空间
static final String ns = "http://xmlns.oracle.com/HelloWorld";
public static void main(String args[]){
Call call = null;
try {
call = createCall();
Vector rtn = (Vector) call.invoke(createRequest());
parse(rtn);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (FactoryConfigurationError e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/*
* 创建Call对象,对设置相关属性,注意:其中的属性应该是通过分析WSDL文件由程序动态获得来赋值,
* 这里全部简化为静态赋值
*/
static Call createCall() throws MalformedURLException, ServiceException{
org.apache.axis.client.Service s = new org.apache.axis.client.Service();
Call call = (Call) s.createCall();
call.setTargetEndpointAddress(new URL("http://robin:9700/orabpel/default/HelloWorld/1.0"));
call.setSOAPActionURI("process");
call.setOperationName("process");
call.setProperty(Call.OPERATION_STYLE_PROPERTY, Style.DOCUMENT.getName());
call.setPortName(new QName(ns, "HelloWorldPort"));
call.setPortTypeName(new QName(ns, "HelloWorld"));
return call;
}
/*
*创建请求参数,实际上就是构建DOM片断,根据Web service对输入参数的要求来构建,要多复杂,都可以实现,
*这就是Docuemnt的好处,省去了复杂对象的序列化。
*/
static Object[] createRequest() throws ParserConfigurationException, FactoryConfigurationError{
DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = db.newDocument();
Element root = doc.createElementNS(ns, "HelloWorldProcessRequest");
Element input = doc.createElementNS(ns, "input");
input.appendChild(doc.createTextNode("robin"));
root.appendChild(input);
doc.appendChild(root);
return new Object[]{new SOAPBodyElement(root)};
}
// 对返回结果进行解析,并打印。
static void parse(Vector v) throws Exception{
Document doc = ((SOAPBodyElement) v.get(0)).getAsDocument();
Element root = doc.getDocumentElement();
OutputFormat of = new OutputFormat();
of.setIndent(4);
System.out.println(new DOMSerializerImpl().writeToString(root));
}
}
上述代码运行输出结果为:
<?xml version="1.0"?>
<HelloWorldProcessResponse xmlns="http://xmlns.oracle.com/HelloWorld">
<result xmlns="http://xmlns.oracle.com/HelloWorld">robin</result>
</HelloWorldProcessResponse>
上面的代码很简单,需要说明的是:采用Document调用,实际上invoke方法的参数是一个元素类型为SOAPBodyElement的对象数组,而返回结果是一个元素类型的SOAPBodyElement的Vector对象。
这一小节介绍如何编写一个自定义的注解类型,以及如何应用JDK5.0 java.lang.annotation包中提供的4种注解:
@Documented,@Retention,@Target,@Inherited
1. 编写自定义@Todo注解经常我们在写程序时,有时候有些功能在当前的版本中并不提供,或由于某些其它原因,有些方法没有完成,而留待以后完成,我们在javadoc中用@TODO来描述这一行为,下面用java注解来实现。
public @interface Todo { } // Todo.java如果你想让这个注解类型能够自省的话,给它加上@Todo注解,写法如下:
@Todo
public @interface Todo{ }下面我们给这个注解接受参数的能力,代码如下:
@Todo("Just articleware")
public @interface Todo{
public enum Priority { LOW, MEDIUM, HIGH }
String value();
String[] owners() default "";
Priority priority() default Priority.MEDIUM;
}
注意:注解类性所能接受的参数类型有着严格的规则:
a. 参数类型只能是:primitive, String, Class, enum, annotation, 或者是数组;
b. 参数值不能为空,因此每一个参数值都要定义一个缺省值;
c. 名字为value的参数可以用简便的方法来设置;
d. 参数的写法如同写简单方法(看如上代码),不允许加入参数,不允许有throws子句等。
在上面的代码中,我们为@Todo定义了3个参数, 分别是value, owners, priority. 注意:由于value的特殊性,它的的却省值可以由上面代码中的"Just articleware"来定义,当然你也可以单独写一个缺省值。
下面看一个应用@Todo注解的例子:
@Todo(
value="Class scope",
priority=Unfinished.Priority.LOW
)
public class TodoDemo {
@Todo("Constructor scope")//通过快捷方式,设置value的值
public TodoDemo() { }
@Todo(owner="Jason", value="Method scope")
public void foo() { }
}
上面的代码很简单,不多介绍。
下面我们想让@Todo不能应用在fields, parameters, 或者local variables(因为这对我们来说没有意义);它应当可以出现在javadoc中;在运行是具有持久性。要实现这些特性,就需要annotation包的支持啦。
2. 应用annotation包的支持1)@Documented
类和方法的annotation缺省情况下是不出现在javadoc中的,为了加入这个性质我们用@Documented
应用代码如下(简单,不多介绍):
package com.robin;
import java.lang.annotation.*;
@Todo("Just articleware")
@Documented
public @interface Todo{ ...
2)@Retention
用来表明你的annotation的有效期,可以有三种选择(如图所示):
以下示例代码应用RUNTIME策略
package com.robin;
import java.lang.annotation.*;
@Todo("Just articleware")
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface Todo{ ...
3) @Target
@Target注解表明某个注解应用在哪些目标上,可选择如下范围:
- ElementType.TYPE (class, interface, enum)
- ElementType.FIELD (instance variable)
- ElementType.METHOD ElementType.PARAMETER
- ElementType.CONSTRUCTOR
- ElementType.LOCAL_VARIABLE
- ElementType.ANNOTATION_TYPE (应用于另一个注解上)
- ElementType.PACKAGE
按我们的功能要求,代码如下:
package com.robin;
import java.lang.annotation.*;
@Todo("Just articleware")
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD,
ElementType.CONSTRUCTOR,ElementType.ANNOTATION_TYPE,
ElementType.PACKAGE})
public @interface Todo{ ...
4) @Inherited
@Inherited表明是否一个使用某个annotation的父类可以让此annotation应用于子类。
示例代码如下:
package com.robin;
import java.lang.annotation.*;
@Todo("Just articleware")
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD,
ElementType.CONSTRUCTOR,ElementType.ANNOTATION_TYPE,
ElementType.PACKAGE})
@Inherited
public @interface Todo{
public enum Priority { LOW, MEDIUM, HIGH }
String value();
String[] owners() default "";
Priority priority() default Priority.MEDIUM;
}