Cool eye

BlogJava 首页 新随笔 联系 聚合 管理
  63 Posts :: 4 Stories :: 3 Comments :: 0 Trackbacks

#

属性

描述

onreadystatechange

每次状态改变所触发事件的事件处理程序

readyState

对象状态值:

  • 0 = 未初始化(uninitialized)
  • 1 = 正在加载(loading)
  • 2 = 加载完毕(loaded)
  • 3 = 交互(interactive)
  • 4 = 完成(complete)

responseText

从服务器进程返回的数据的字符串形式

responseXML

从服务器进程返回的DOM兼容的文档数据对象

status

从服务器返回的数字代码,比如404(未找到)或200(就绪)

statusText

伴随状态码的字符串信息

posted @ 2006-08-16 13:24 joeyeezhang 阅读(182) | 评论 (0)编辑 收藏

BOOKS GENERAL

Jolt Winner: Prefactoring by Ken Pugh (O''Reilly)

Productivity Winners:
• Innovation Happens Elsewhere: Open Source as Business Strategy by Ron Goldman, Richard P. Gabriel (Morgan Kaufmann)
• Producing Open Source Software: How to Run a Successful Free Software Project by Karl Fogel (O''Reilly)
• The Art of Project Management by Scott Berkun (O''Reilly)

BOOKS TECHNICAL

Jolt Winner: Agile Web Development with Rails by Dave Thomas, David Hansson, Leon Breedt and Mike Clark (Pragmatic Bookshelf)

Productivity Winners:
• Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries by Krzysztof Cwalina and Brad Abrams (Addison-Wesley)
• Practical Common Lisp by Peter Seibel (Apress)
• Why Programs Fail: A Guide to Systematic Debugging by Andreas Zeller (Morgan Kaufmann)

ENTERPRISE PROJECT MANAGEMENT

Jolt Winner: WelcomRisk 2.6 (Welcom)

Productivity Winners:
• Corticon Business Rules Management 4.0 (Corticon)
• JBoss 2 Portal (JBoss)
• Visual Studio Team System 2005 (Microsoft)

DATABASE ENGINES AND DATA TOOLS

Jolt Winner: Microsoft SQL Server 2005 (Microsoft)

Productivity Winners:
• Berkeley DB 4.4 (Sleepycat Software)
• Google Maps API 2005 (Google)
• MySQL 5.0 (MySQL)

DEFECT TRACKING, CHANGE AND CONFIGURATION MANAGEMENT

Jolt Winner: Perforce SCM 2005 (Perforce)

Productivity Winners:
• FogBugz 4.0 (Fog Creek)
• Guiffy SureMerge 7.0 (Guiffy Software)
• JIRA 3.4 (Atlassian Software)

DESIGN TOOLS AND MODELING

Jolt Winner: Lattix LDM 2.0 (Lattix)

Productivity Winners:
• Borland Together 2006 for Eclipse (Borland)
• Enterprise Architect 6.0 (Sparx Systems)
• MindManager Pro 6.0 (Mindjet)

DEVELOPMENT ENVIRONMENTS

Jolt Winner: Visual Studio Team System 2005 (Microsoft)

Productivity Winners:
• Eclipse SDK 3.1 (Eclipse.org)
• IntelliJ IDEA 5.0 (JetBrains)
• Komodo 3.5 (ActiveState)

LIBRARIES, FRAMEWORKS AND COMPONENTS

Jolt Winner: .NET Framework 2.0 (Microsoft)

Productivity Winners:
• Dundas Chart for .NET 5.0 (Dundas Software)
• Qt 4.0 (Trolltech)
• Spring Framework 1.2.6 (SpringFramework.org)

MOBILE DEVELOPMENT TOOLS

Jolt Winner: Crossfire 5.6 (AppForge)

Productivity Winners:
• Carbide.c++ Express (Nokia)
• Flash Lite 2.0 (Adobe)
• NetBeans IDE 4.1 (Sun Microsystems)

QUALITY PROJECT MANAGEMENT

Jolt Winner: Rally 5.6 (Rally Software Development)

Productivity Winners:
• CollabNet Enterprise Edition with Project Dashboard/Task Management 2005 (CollabNet)
• QACenter Enterprise Edition 5.1 (Compuware)
• TargetProcess Suite 1.4 (TargetProcess)

SECURITY TOOLS

Jolt Winner: Elemental Compliance System 1.4 (Elemental)

Productivity Winners:
• CodeAssure 2.0 (Secure Software)
• DevPartner SecurityChecker 1.0 (Compuware)
• Fortify Security Tester 1.0 (Fortify)

TESTING TOOLS

Jolt Winner: VMTN Subscription 2005 (VMware)

Productivity Winners:
• Agitator 3.0 (Agitar Software)
• AQtime 4.7 (AutomatedQA)
• Clover 1.3 (Cenqua)

UTILITIES

Jolt Winner: Camtasia Studio 3.0 (TechSmith)

Productivity Winners:
• DevPartner Studio 8 (Compuware)
• Fog Creek Copilot 1.2 (Fog Creek Software)
• ReSharper 1.5 (JetBrains)

WEB DEVELOPMENT TOOLS

Jolt Winner: Rails 1.0 (rubyonrails.org)

Productivity Winners:
• JBoss Application Server 4x (JBoss)
• Macromedia Studio 8 2005 (Adobe)
• Zend Studio - Enterprise Edition 5.0 (Zend)

HALL OF FAME WINNER:

• Visual Studio Professional Edition (Microsoft)

posted @ 2006-06-24 23:45 joeyeezhang 阅读(297) | 评论 (0)编辑 收藏

如何用Script语言访问网页的某个元素及其相关的应用 作者:时の卵
A.例子一:如何获得页面中的所有HTML元素?
<HTML>
<HEAD><TITLE>显示页面中所有的HTML元素</TITLE>
<SCRIPT LANGUAGE="JavaScript">
function showElements() {
var tag_names = "";
for (i=0; i<document.all.length; i++)
tag_names = tag_names + document.all(i).tagName + " ";
alert("本页面中的元素有 " + tag_names);
}
</SCRIPT>
</HEAD>
<BODY onload="showElements()">
<H1>欢迎</H1>
<P>这是一个 <B>测试</B> 文件.</P>
</BODY>
</HTML>


B.例子二:如何获得元素的子元素?
<HTML id=theHTML>
<HEAD>
<TITLE>显示所有元素及theHTML的子元素</TITLE>
<SCRIPT language=JavaScript>
function showme() {
alert('theHTML下共有 ' + window.theHTML.all.length+' 个HTML的元素');

for (i=0; i < theHTML.all.length;i++)
{
alert(theHTML.all[i].tagName);
}
alert('theHTML下的子元素共有 ' + window.theHTML.children.length+' 个')

;
for (i=0; i < theHTML.children.length;i++)
{
alert(theHTML.children[i].tagName);
}
}
</SCRIPT>
</HEAD>
<BODY onload=showme()>
<DIV></DIV>
</BODY>
</HTML>

C.例子三:如何获得页面内某个元素的内容和改变它的某些属性?
<html>
<head>
<title>Untitled Document</title>
<script language="JavaScript">
function getTags(){
var get_tables = document.all.tags("TABLE");
for (i=0; i<get_tables.length; i++)
alert('第'+(i+1)+'个TABLE元素内的内容为:\n'+get_tables(i).innerHTML

+'\n'+'当你按下确定后这个TABLE的属性之一[BORDER]的值将变为1');
get_tables(i-1).border = 1;
}
</script>
</head>
<body onLoad=getTags()>
<table width="200" border="0" cellspacing="0" cellpadding="0">
<tr>
<td>
<a href="http://www.flashabc.com">HTTP://WWW.FLASHABC.COM</a></td>
</tr>
</table>
</body>
</html>

D.例子四:用另一种方法来改变元素的属性的值
<HTML>
<HEAD><TITLE>改改改!</TITLE>
<SCRIPT LANGUAGE="JavaScript">
function showAndSetAlignment() {
alert(MyHeading.getAttribute("align"));
MyHeading.setAttribute("align","center");
}
</SCRIPT>
</HEAD>
<BODY onload="showAndSetAlignment()">
<H1 ID=MyHeading ALIGN="left">欢迎光临</H1>
<P>HTTP://WWW.FLASHABC.COM
</BODY>
</HTML>

E.例子五:显示出页中的元素结构
<HTML>
<HEAD><TITLE>Elements: Hierarchy</TITLE>
<SCRIPT LANGUAGE="JScript">
function showHierarchy() {
var depth = 0;
var msg = document.all(0).tagName;
for (i=1; i<document.all.length; i++) {
if (document.all(i-1).contains(document.all(i))==true) {
depth = depth + 1;
} else {
var elParent = document.all(i-1).parentElement;
for ( ; depth>0; depth--) {
if (elParent.contains(document.all(i))==true)
break;
elParent = elParent.parentElement;
}
}
msg = msg + "\n";
for (j=1; j<=depth; j++)
msg = msg + " ";
msg = msg + document.all(i).tagName;
}
alert("这个页面中包含的元素为\n" + msg);
}
</SCRIPT>
</HEAD>
<BODY onload="showHierarchy()">
<H1>欢迎光临</H1>
<P>你看到预想的<B>结果</B> 了吗.
</BODY>
</HTML>

还有几个小例子,你自己看看就会明白是做什么用途啦
var coll = document.all.tags("H1");
if (coll.length>0)
coll(0).align="center";

var coll = document.all.tags("IMG");
if (coll.length>0)
coll(0).src="newimage.gif";

var coll = document.all.tags("H1");
for (i=0; i<coll.length; i++)
coll[i].style.color = "green";

下一篇:用showModalDialog来打开页面 作者:时の卵
 


 

posted @ 2006-05-29 16:42 joeyeezhang 阅读(280) | 评论 (0)编辑 收藏


1.Hashtable是Dictionary的子类,HashMap是Map接口的一个实现类;
2.Hashtable中的方法是同步的,而HashMap中的方法在缺省情况下是非同步的。即是说,在多线程应用程序中,不用专门的操作就安全地可以使用Hashtable了;而对于HashMap,则需要额外的同步机制。但HashMap的同步问题可通过Collections的一个静态方法得到解决:
Map Collections.synchronizedMap(Map m)
这个方法返回一个同步的Map,这个Map封装了底层的HashMap的所有方法,使得底层的HashMap即使是在多线程的环境中也是安全的。
3.在HashMap中,null可以作为键,这样的键只有一个;可以有一个或多个键所对应的值为null。当get()方法返回null值时,即可以表示HashMap中没有该键,也可以表示该键所对应的值为null。因此,在HashMap中不能由get()方法来判断HashMap中是否存在某个键,而应该用containsKey()方法来判断。
posted @ 2006-05-27 13:16 joeyeezhang 阅读(182) | 评论 (0)编辑 收藏


《最后期限》-项目管理重要原则


优质管理的四大要素:
    选择正确的人。
    为他们分配正确的工作。
    保持他们的积极性。
    帮助团队凝聚起来并保持团队的凝聚力。
    (其他一切都只是"文案"。)


安全和变化
    除非感到安全,否则人们就不能去迎接变化。
    在所有成功的工程中(以及在绝大多数其他有价值的工作中),变化都是基本的要素之一。
    安全感的缺乏会让人们反对变化。
    逃避风险是致命的,因为这会让你也得不到与风险同在的利益。
    人们可能会因为来自客观世界的直接的恐吓而觉得没有安全感,但是如果察觉到管理者可能滥用权力来惩罚自己,他们也会觉得没有安全感。


负面效应
    威胁不是提高业绩最好的方法。
    如果分配的时间一开始就不够,不管威胁有多么吓人,工作也无法按时完成。
    更糟糕的是,如果目标没有实现,你就必须兑现你的威胁。


管理者必需的身体部位
    管理涉及到心、肠胃、灵魂和鼻子。
    因此……用心来领导,相信你的肠胃(相信你的预感),构筑团队的灵魂,训练一个能嗅出谎言的鼻子。


用指挥战争来作为管理的一个比喻
    在战役开始的时候,管理者真正的工作已经完成了。


面试和招聘
    招聘涉及到所有与管理相关的身体部位:心、灵魂、鼻子和肠胃(但是主要是肠胃)。
    不要试图单独去招聘——两副肠胃远比一副肠胃的两倍要好。
    对于新的雇员,让他们承担与以前曾经成功过的同样难度的项目,把有挑战性的目标推迟到下一次。
    征求提示:你最希望雇的那个人可能还知道其他很好的人选。
    多听,少说。
    如果先把材料整理好,那么所有的事情都会进行得更好。



生产力的提高
    没有"短期生产力提高"这样的东西。
    生产力的提高是来自长期投资的。
    任何承诺立刻见效的东西都很可能是江湖游医所卖的万灵油。


风险控制
    通过控制风险来管理项目。
    为每个项目创建并维护风险统计表。
    跟踪根源性的风险,而不只是最后那讨厌的结果。
    评估每种风险具体化的概率和可能造成的开销。
    对于每种风险,预测标志其具体化的早期征兆。
    任命一个风险控制官,这个人不应该维护组织内部"我能行"的态度。
    建立简单的(可能是匿名的)通道,让坏消息能传递到高层。


防止失败
     壮士断腕。
     控制住失败比优化成功更能提高你全面的成绩。
     要有闯劲,尽早取消失败的工作。
     除非必要,否则就不要自己去凝聚一个团队:出去找一个已经成型的团队来用。
     保持好的团队在一起(只要他们自己愿意),以帮助你的继任者避免团队凝聚得慢或者不能凝聚的问题。
     把凝聚在一起的团队--准备好、并且也愿意接受新的工作--作为项目的收获之一。
     项目开始时浪费的一天和最后阶段浪费的一天对项目造成的伤害是同等的。
    有无数种方法可以浪费一天的时间……但是没有任何一种方法可以拿回一天的时间。


开发过程的建模和模拟
     将你关于完成工作过程的直觉建模。
     在同事的交流中使用这些模型,以便交流、提炼关于项目运转的思想。
     用模型来模拟项目的结果。
     根据实际的结果来调整模型。


"病态的政治"
    每一天,你都必须准确度拿自已的工作去打赌......
    ......但是这也不能保证"病态的政治"不会影响你。
    "病态的政治"可能在任何地方出现,哪怕是在最健康的组织里面。
    "病态的政治"的特征:对个人权势的渴望超过了组织本身的目标。
    即使这种不合理的目标与组织的目标背道而驰,它也可能出现。
    "病态的政治"的副作用:它使精简的项目变得危险。


度量
    度量每个产品的规模。
    不要执着于单位——在等待客观度量的时候,先用你自己的主观单位。
    从所有能得到的原始数据(可计算的软件特征)自己构造度量单位。
    不断完善你的度量方程式,直到它的计算结果与原始数据库中的项目工作量有最好的对应关系。
    借助数据库画一条趋势线,把预期的工作量作为人造度量单位值的函数显示出来。
    现在,针对每个要度量的项目,计算出人造度量单位值,并根据这个值在趋势线上找到预期工作量值。
    用生产力趋势周围的干扰水平作为映射的公差指示。


过程和过程改进
    好的过程和持续的过程是绝好的目标。
    它们也是非常自然的目标:优秀的技术工作者一定会关注它们,而不管你是否告诉他们。
    正式的过程改进程序需要花钱、花时间;特定的过程改进工作还会延缓项目进度。尽管最终体现出生产力上的收获,它们也不可能抵消花在过程改进上的时间。
    但是项目有希望从单个的、正确选择的方法改进中得到足够的收益,并赢回为这次改变付出的时间和金钱。
    在项目进行过程中,不要希望在超过一个地方的范围内实施必改进。多种技术的改进程序(比如说提高整整一个CMM等级)很可能让项目比不实施这些程序完成得更晚。
    标准过程的危险就在于人们可能失去重要的走捷径的机会。
    特别是对于人员超编的项目,标准的过程看去会很严谨,因为它们制造出了足够的工作(有用的和无用的),让所有人都忙于不停。


改变完成工作的方式
    如果不大幅减少调试时间,就没有办法让项目大幅度提前完成。
    高速完成的项目用在调试上的时间成比例地少得多。
    高速完成的项目用在设计上的时间也成比例地多得多。
    如果你不关心别人, 不照顾别人,就别想让他们做一些不同寻常的事情。如果要让他们改变,就必须去了解(并赞赏)他们的过去。


压力的效果
    压力之下的人无法更快的思考。
    增加加班时间只会降低生产力。
    短期的压力乃至于加班可能是有用的策略,因为它们能使员工集中精力,并且让他们感到工作的重要性。但是长期的压力肯定是错误的。
    经理们之所以会施加那么多压力,也许是因为他们不知道该做什么,或者因为其他办法的困难而感到气馁。
    最坏的猜想:使用压力和加班的真正原因是为了在项目失败的时候让所有人看上去能好一点。
   
愤怒的经理
    管理中的愤怒和羞辱是会传染的。如果高级管理者喜欢骂人,低级管理者也会有样学样(就象经常被骂的小孩很容易变成爱骂人的父母)。
    管理中的辱骂常被认为是一种刺激,可以让员工提高效率。在" 胡萝卜加大棒"的管理策略中,辱骂是最常见的"大棒"。但是,哪有人被辱骂之后还能做得更好的?
    如果经理使用辱骂的方法来刺激员工,这就表现经理的无能,而不是员工的无能。


含糊的规格文档
    规格文档中的含糊标志着不同的系统参与者之间存在未解决的冲突。
    如果一份规格文档不包含完整的输入输出列表,那么它就是毫无希望的:它根本就没有开始说明任何东西。
    没有人会告诉你一份规格文档是不是糟糕。人们往往倾向于责备自己,而不责备文档。


冲突
    只要在开发过程中有多个参与者,就一定会有冲突存在。
    创建、安装系统的业务中特别容易出现冲突。
    绝大多数系统开发团队都缺乏解决冲突的能力。
    冲突应当引起重视。冲突并不是缺乏职业道德的行为。
    应当提前声明:所有人的"赢"都是受重视的。确保每个级别的人都能赢。
    谈判困难,调解容易。
    如果两个人的利益是完全或者部分相斥的,预先做好安排,准备好请双方通过调解来解决冲突。
    记住:我们都站在同一边;跟我们对立的,是我们要解决的问题。
   
催化剂的角色
    有这样一种催化剂式的人格。这样的人会帮助团队成型并凝聚,保持团队的健康和生产力,从而对项目作出贡献。就算"催化剂"别的什么都不干(其实,通常他们还会干很多别的事),这种催化剂的角色也是重要而有价值的。
    调解是"催化剂"的一项特殊工作。调解是可以学的,而且只需要很小的投资就能学会。
    调解应该从一个小小的仪式开始。"我能帮你们调解一下吗?"在解决冲突的时候,这是必要的第一个步骤。


人类的错误
    将你置于死的,不是你不知道的东西……而正是你"知道"绝不会置你于死地的东西。


人员安排
    在早期,人员超编会迫使项目跨过关键的设计阶段(这是为了让所有的人都有事可做)。
    如果在设计完成之前, 工作先被分给了许多人,那么人与人之间、工作与工作之间的接口就会很复杂。
    这会使团队内部耦合度提高,会议时间、重复劳动和无效的工作都会增加。
    理想的人员安排是这样的:在项目的大部分时间内由小型核心团队来做设计工作,在开发的最后阶段(时间安排的最后1/6)加入大量的人手。
    可怕的猜想:时间安排紧迫的项目,与时间安排比较合理的项目比起来,完成的时间反而会更长。


项目社会学
    让不必与会的人可以放心离开,从而保持会议的精简。有一份公开的议程,并严格执行,这是最简单的办法。
    项目需要仪式。
    用小小的仪式来使人们注意项目的目标的理想状态:小规模会议、零缺陷工作等等。
    采取行动,防止人们随便发怒。
    记住:愤怒=恐惧。随便对下级发怒的经理一定是因为恐惧才会这样做的。
    意见:如果所有人都懂得"愤怒=恐惧"这个道理,就能明显看出发怒的人是在害怕。由于无法隐瞒自己的恐惧,他也就不会再生气了。(这不能解决这些生气的人的问题,但是肯定可以让其他人好受一些。)
   
"病态的政治"(旧话重提)
    别想根治一个病态的人。
    不要浪费时间,也不要因为尝试治疗上司的病态而使自己受到威胁。
    有时候,你唯一的的选择就是等待,等问题自己解决,或者等一个让你继续前进的机会。
    奇迹是有可能发生的(但是千万别去指望它)。


精兵简政
    精兵简政是失败公司使用的办法,它使员工负但失败的责任。
    公司的目标应该正好相反:兴旺而人性化。
    当你听到"精兵简政"这个词的时候,请记住它的弦外之音:失败和恐吓。


基本常识
    项目既需要目标,也需要计划。
    而且这两者应该不同。

posted @ 2006-05-24 21:31 joeyeezhang 阅读(206) | 评论 (0)编辑 收藏

tag
>“山高人为峰”,这句话也可以用在技术的研究上。

   jsp规范里,标签具有比javabean更丰富的运行时协议。它可以非常机密的和jsp的表示逻辑联系在一起,同时,又具有javabean相同业务处理能力。所以,标签的学习成为迫切的需要,但为了满足实际项目的开发,自定义标签的学习是不容错过的。

   过实现接口或者继承现有的类,我们就可以开发自定义的标签。

   用的接口有:             JspTag

                       Tag       SimpleTag<----SimpleTagSupport

               IterationTag <----TagSupport           

                    BodyTag<----BodyTagSupport

   定义标签的开发包括两个部分的开发:

(1)、开发标签的处理程序(java类)

(2)、标签描述文件(.tld文件)

   定义标签的种类有许多,可以根据实际项目的需要进行编写。但为了不重复的开发轮子,jsp标准推出JSTL(标准标签库)。

   始我们的旅行吧,只要是快乐的,谁都想干,做的好与不好就另当别论了。

(1)从Hello World开始吧,自定义一个类它实现Tag接口,Tag接口主要定义的是标签声明周期的方法,比如:doStartTag(),doEndTag()等,通过PageContext对象来访问Jsp页面的上下文:

package com.xmddl.tag.demo;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.Tag;

public class HelloTag implements Tag {
 private PageContext context;
 private Tag parent;
 public void setPageContext(PageContext ctx) {
  this.context=ctx;

 }

 public void setParent(Tag tag) {
  this.parent=tag;

 }

 public Tag getParent() {
  return this.parent;
 }

 public int doStartTag() throws JspException {
  System.out.println("doStartTag");
  return Tag.SKIP_BODY;
 }

 public int doEndTag() throws JspException {
  System.out.println("doStartTag");
  try {
   this.context.getOut().write("Hello World");
  } catch (Exception e) {
   e.printStackTrace();
  }
  return Tag.EVAL_PAGE;
 }

 public void release() {
  // TODO Auto-generated method stub
 }

}

 Tag接口中静态常量:

Tag.SKIP_BODY

Tag.EVAL_PAGE

Tag.EVAL_BODY_INCLUDE

Tag.SKIP_PAGE

(2)编写标签描述文件(.tld):

<?xml version="1.0" encoding="UTF-8" ?>
<taglib xmlns="
http://java.sun.com/xml/ns/j2ee "
    xmlns:xsi="
http://www.w3.org/2001/XMLSchema-instance "
    xsi:schemaLocation="
http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd "
    version="2.0">

  <description>xmddl 1.1 hello library</description>
  <display-name>xmddl hello</display-name>
  <tlib-version>1.1</tlib-version>
  <short-name>hello</short-name>
  <uri>http://www.xmddl.com/tag</uri>
 
 
<tag>
    <description>我的Hello World</description>
    <name>hello</name>
    <tag-class>com.xmddl.tag.demo.HelloTag</tag-class>
    <body-content>empty</body-content>
  </tag>

</taglib>

(3)、在web.xml中对标签的引用:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "
http://java.sun.com/dtd/web-app_2_3.dtd ">
<web-app>
 <taglib>
  
<taglib-uri>http://www.xmddl.com/tag</taglib-uri>
  <taglib-location>/WEB-INF/mytag.tld</taglib-location>
 </taglib>
</web-app>

(4)、编写测试页面:

<%@ page language="java" pageEncoding="UTF-8" import="java.util.*"%>
<%@ taglib uri="http://www.xmddl.com/tag" prefix="lu"%>
<html>
  <head>
    <title>MyJsp.jsp</title>
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">   
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
  </head>
 
  <body>
    <h1>This is a test tag page for person.</h1> <br>
  
<lu:hello/>
  </body>
</html>
下面看看标签中的属性是如何使用的,我们直接继承TagSupport类来编写:

 package com.xmddl.tag.demo;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.Tag;
import javax.servlet.jsp.tagext.TagSupport;

public class HelloSupport extends TagSupport {
 private String value;
 private static final long serialVersionUID = 1L;
 public HelloSupport(){
  super();
 }
 public int doStartTag() throws JspException {
  System.out.println("doStartTag");
  return TagSupport.EVAL_BODY_INCLUDE;
 }

 public int doEndTag() throws JspException {
  System.out.println("doEndTag");
  try {
   this.pageContext.getOut().write("标签的属性值:"+this.value);
  } catch (Exception e) {
   e.printStackTrace();
  }
  return Tag.EVAL_PAGE;
 }
 public int doAfterBody() throws JspException{
  System.out.println("doAfterBody");
  try {
   this.pageContext.getOut().write("<br>以上为标签的内容<br>");
  } catch (Exception e) {
   e.printStackTrace();
  }
  return TagSupport.EVAL_BODY_INCLUDE;
  
 }
 public String getValue() {
  return value;
 }
 public void setValue(String value) {
  this.value = value;
 }
}
======================

...

<tag>
    <name>hellosupport</name>
    <tag-class>com.xmddl.tag.demo.HelloSupport</tag-class>
    <body-content>JSP</body-content>
    <attribute>
        <name>value</name>
        <required>true</required>
        <rtexprvalue>false</rtexprvalue>
    </attribute>
  </tag>

...

=======================

<%@ page language="java" pageEncoding="gb2312" import="java.util.*"%>
<%@ taglib prefix="lu" uri="
http://www.xmddl.com/tag " %>
<html>
  <head>
  </head>
  <body>

    <h1>This is a test tag page for person.</h1> <br>
  <lu:hellosupport value="red">xmddl</lu:hellosupport>
  </body>
</html>

 利用TagSupport带来很大的方便,只要重写其中的部分方法即可实现一个标签处理程序,以上开发的标签程序和JSTL1.1标签库一起使用时出现一些疑问,原来标签的uri=" http://java.sun.com/jsp/jstl/core ",但是,在如下的测试中会发现c:out中的值输不出来,所以,只能改为uri=" http://java.sun.com/jstl/core ",

<%@ page language="java" pageEncoding="gb2312" import="java.util.*"%>
<%@ taglib prefix="lu" uri="
http://www.xmddl.com/tag " %>
<%@ taglib prefix="c" uri="
http://java.sun.com/jstl/core " %>

<html>
  <head>
  </head>
  <body>

    <h1>This is a test tag page for person.</h1> <br>
    <%request.setAttribute("name","xmddl"); %>
    <%session.setAttribute("names","xmddls"); %>
   
  <lu:hellosupport value="red">xmddl</lu:hellosupport><hr>
  <c:forEach begin="1" end="5" step="1">
   name=<c:out value="${name}"></c:out>
   names=<c:out value="${names}"></c:out><br>
  </c:forEach>
  </body>
</html>
输出如下:

This is a test tag page for person.
xmddl
以上为标签的内容
标签的属性值:red


name=xmddl names=xmddls
name=xmddl names=xmddls
name=xmddl names=xmddls
name=xmddl names=xmddls
name=xmddl names=xmddls

接着看看迭代标签的开发,首先,我们关注的是接口IterationTag,还有它的实现类TagSupport,接口BodyTag对IterationTag的扩展,还有BodyTag的实现类BodyTagSupport。

package com.xmddl.tag.demo;

import java.io.IOException;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.BodyTagSupport;
public class MyIteratorSupport extends BodyTagSupport {
 private static final long serialVersionUID = 1L;
 public String count;
 public String strColor;
 private int cou;
 
 public void setCount(String count) {
  this.count = count;
  cou=Integer.parseInt(count);
 }
 
 public int doAfterBody() throws JspException {
  try {
   this.pageContext.getOut().write("<br>");
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  if(cou>1){
   cou--;
   return MyIteratorTag.EVAL_BODY_AGAIN;
  }else{
   return MyIteratorTag.SKIP_BODY;
  }
 }
 public int doStartTag() throws JspException {
  try {
   this.pageContext.getOut().write("<font color='"+this.strColor+"'>");
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  return MyIteratorTag.EVAL_BODY_INCLUDE;
 }

 public int doEndTag() throws JspException {
  try {
   this.pageContext.getOut().write("</font>");
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  return MyIteratorTag.EVAL_PAGE;
 }

 public int getCou() {
  return cou;
 }

 public void setCou(int cou) {
  this.cou = cou;
 }

 public String getCount() {
  return count;
 }

 public String getStrColor() {
  return strColor;
 }

 public void setStrColor(String strColor) {
  this.strColor = strColor;
 }

}
==============

。。。

<tag>
    <description>对颜色的设置</description>
    <name>myColor</name>
    <tag-class>com.xmddl.tag.demo.MyIteratorSupport</tag-class>
    <body-content>JSP</body-content>
    <attribute>
        <name>count</name>
        <required>true</required>
    </attribute>
    <attribute>
        <name>strColor</name>
        <required>false</required>
    </attribute>
   </tag>

。。。

==============

<%@ page language="java" pageEncoding="gb2312" import="java.util.*"%>
<%@ taglib prefix="lu" uri="http://www.xmddl.com/tag" %>
<html>
  <head>
  </head>
  <body>

    <h1>This is a test tag page for person.</h1> <br>
    <lu:myColor count="3" strColor="blue">xmddl</lu:myColor>
  </body>
</html>

输出如下

This is a test tag page for person.


xmddl
xmddl
xmddl

posted @ 2006-03-21 10:58 joeyeezhang 阅读(230) | 评论 (0)编辑 收藏

<html locale="true">
<head>
<title><bean:message key="hrUsers.maint" /></title>
<script language="javascript">
var textId;
var text;
function calendarDefalut(name)  //定义dateSelector的display方法,它将实现一个日历形式的日期选择框。
{
  var myDate=new Date();
 this.year=myDate.getFullYear();  //定义year属性,年份,默认值为当前系统年份。
   this.month=myDate.getMonth()+1;  //定义month属性,月份,默认值为当前系统月份。
 calendar('default',name,this.year+'/'+this.month);
}
function calendar(id,name,value)  //定义dateSelector的display方法,它将实现一个日历形式的日期选择框。
{
 
  textId = id;
 
 
  document.write("<style type=text/css>");
  document.write("  .ds_font td,span  { font: normal 12px 宋体; color: #000000; }");
  document.write("  .ds_border  { border: 1px solid #000000; cursor: hand; background-color: #F7F7F7 }");
  document.write("  .ds_border2  { border: 1px solid #000000; cursor: hand; background-color: #F7F7F7 }");
  document.write("</style>");
 

 

  document.write("        <span width=12% onmouseover=this.className='ds_border' onmouseout=this.className='' onclick=subYear() title='减小年份'>&lt;&lt;&nbsp;</span>");
  document.write("        <span width=12% onmouseover=this.className='ds_border' onmouseout=this.className='' onclick=subMonth() title='减小月份'>&lt;</span>");
  document.write("        <span width=52%><input id='"+id+"'  type='text' name='"+name+"' value="+value+" readonly='readonly' size='3' style='border-style: solid; border-color: #FFFFFF;border: 0px solid #000000;  background-color: #F7F7F7'></span>");
  document.write("        <span width=12% onmouseover=this.className='ds_border' onmouseout=this.className='' onclick=addMonth() title='增加月份'>&gt;&nbsp;</span>");
  document.write("        <span width=12% onmouseover=this.className='ds_border' onmouseout=this.className='' onclick=addYear() title='增加年份'>&gt;&gt;</span>");


   text= document.getElementById(textId);
  }

function subYear()  //减小年份
{
 
  var value = text.value;
  text.value = (eval(value.substr(0,4))-1)+'/'+value.substr(5,2);
 }

function addYear()  //增加年份
{

  var value = text.value;

  text.value = (eval(value.substr(0,4))+1)+'/'+value.substr(5,2);
 }

function subMonth()  //减小月份
{
  var value = text.value;

  var month=eval(value.substr(5,2))-1;
  var year = value.substr(0,4)
  if(month==0)
  {
    month=12;
    year = eval(year)-1;
  }
  text.value = year+'/'+month;
 }

function addMonth()  //增加月份
{
   var value = text.value;

  var month=eval(value.substr(5,2))+1;
  var year = value.substr(0,4)
  if(month==13)
  {
    month=1;
    year = eval(year)+1;
   }
  text.value = eval(year)+'/'+month;
}
 </script>
 </HEAD>
ssss:<script language=javascript>calendarDefalut('hrUsers.userNo');</script>
</html>

posted @ 2006-03-03 16:58 joeyeezhang 阅读(249) | 评论 (0)编辑 收藏

<html>

<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<title>New Page 1</title>
<script language=javascript>
var DS_x,DS_y;

function dateSelector()  //构造dateSelector对象,用来实现一个日历形式的日期输入框。
{
  var myDate=new Date();
 
  this.year=myDate.getFullYear();  //定义year属性,年份,默认值为当前系统年份。
  this.month=myDate.getMonth()+1;  //定义month属性,月份,默认值为当前系统月份。
  this.date=myDate.getDate();  //定义date属性,日,默认值为当前系统的日。
  this.inputName='';  //定义inputName属性,即输入框的name,默认值为空。注意:在同一页中出现多个日期输入框,不能有重复的name!
  this.display=display;  //定义display方法,用来显示日期输入框。
}

function display()  //定义dateSelector的display方法,它将实现一个日历形式的日期选择框。
{
  var week=new Array('日','一','二','三','四','五','六');

  document.write("<style type=text/css>");
  document.write("  .ds_font td,span  { font: normal 12px 宋体; color: #000000; }");
  document.write("  .ds_border  { border: 1px solid #000000; cursor: hand; background-color: #DDDDDD }");
  document.write("  .ds_border2  { border: 1px solid #000000; cursor: hand; background-color: #DDDDDD }");
  document.write("</style>");
 
  var M=new String(this.month);
  var d=new String(this.date);
 
  if(M.length==1&&d.length==1){
  document.write("<input style='text-align:center;' id='DS_"+this.inputName+"' name='"+this.inputName+"' value='"+this.year+"-0"+this.month+"-0"+this.date+"' title=双击可进行编缉 ondblclick='this.readOnly=false;this.focus()' onblur='this.readOnly=true' readonly>");}
  else if(M.length==1&&d.length==2){
  document.write("<input style='text-align:center;' id='DS_"+this.inputName+"' name='"+this.inputName+"' value='"+this.year+"-0"+this.month+"-"+this.date+"' title=双击可进行编缉 ondblclick='this.readOnly=false;this.focus()' onblur='this.readOnly=true' readonly>");}
   else if(M.length==2&&d.length==1){
  document.write("<input style='text-align:center;' id='DS_"+this.inputName+"' name='"+this.inputName+"' value='"+this.year+"-"+this.month+"-0"+this.date+"' title=双击可进行编缉 ondblclick='this.readOnly=false;this.focus()' onblur='this.readOnly=true' readonly>");}
   else if(M.length==2&&d.length==2){
  document.write("<input style='text-align:center;' id='DS_"+this.inputName+"' name='"+this.inputName+"' value='"+this.year+"-"+this.month+"-"+this.date+"' title=双击可进行编缉 ondblclick='this.readOnly=false;this.focus()' onblur='this.readOnly=true' readonly>");}


  document.write("<button style='width:60px;height:18px;font-size:12px;margin:1px;border:1px solid #A4B3C8;background-color:#DFE7EF;' type=button onclick=this.nextSibling.style.display='block' onfocus=this.blur()>选择日期</button>");

  document.write("<div style='position:absolute;display:none;text-align:center;width:0px;height:0px;overflow:visible' onselectstart='return false;'>");
  document.write("  <div style='position:absolute;left:-60px;top:20px;width:142px;height:165px;background-color:#F6F6F6;border:1px solid #245B7D;' class=ds_font>");
  document.write("    <table cellpadding=0 cellspacing=1 width=140 height=20 bgcolor=#CEDAE7 onmousedown='DS_x=event.x-parentNode.style.pixelLeft;DS_y=event.y-parentNode.style.pixelTop;setCapture();' onmouseup='releaseCapture();' onmousemove='dsMove(this.parentNode)' style='cursor:move;'>");
  document.write("      <tr align=center>");
  document.write("        <td width=12% onmouseover=this.className='ds_border' onmouseout=this.className='' onclick=subYear(this) title='减小年份'>&lt;&lt;</td>");
  document.write("        <td width=12% onmouseover=this.className='ds_border' onmouseout=this.className='' onclick=subMonth(this) title='减小月份'>&lt;</td>");
  document.write("        <td width=52%><b>"+this.year+"</b><b>年</b><b>"+this.month+"</b><b>月</b></td>");
  document.write("        <td width=12% onmouseover=this.className='ds_border' onmouseout=this.className='' onclick=addMonth(this) title='增加月份'>&gt;</td>");
  document.write("        <td width=12% onmouseover=this.className='ds_border' onmouseout=this.className='' onclick=addYear(this) title='增加年份'>&gt;&gt;</td>");
  document.write("      </tr>");
  document.write("    </table>");

  document.write("    <table cellpadding=0 cellspacing=0 width=140 height=20 onmousedown='DS_x=event.x-parentNode.style.pixelLeft;DS_y=event.y-parentNode.style.pixelTop;setCapture();' onmouseup='releaseCapture();' onmousemove='dsMove(this.parentNode)' style='cursor:move;'>");
  document.write("      <tr align=center>");
  for(i=0;i<7;i++)
 document.write("      <td>"+week[i]+"</td>");
  document.write("      </tr>");
  document.write("    </table>");

  document.write("    <table cellpadding=0 cellspacing=2 width=140 bgcolor=#EEEEEE>");
  for(i=0;i<6;i++)
  {
    document.write("    <tr align=center>");
 for(j=0;j<7;j++)
      document.write("    <td width=10% height=16 onmouseover=if(this.innerText!=''&&this.className!='ds_border2')this.className='ds_border' onmouseout=if(this.className!='ds_border2')this.className='' onclick=getValue(this,document.all('DS_"+this.inputName+"'))></td>");
    document.write("    </tr>");
  }
  document.write("    </table>");

  document.write("    <span style=cursor:hand onclick=this.parentNode.parentNode.style.display='none'>【关闭】</span>");
  document.write("  </div>");
  document.write("</div>");

  dateShow(document.all("DS_"+this.inputName).nextSibling.nextSibling.childNodes[0].childNodes[2],this.year,this.month)
}

function subYear(obj)  //减小年份
{
  var myObj=obj.parentNode.parentNode.parentNode.cells[2].childNodes;
  myObj[0].innerHTML=eval(myObj[0].innerHTML)-1;
  dateShow(obj.parentNode.parentNode.parentNode.nextSibling.nextSibling,eval(myObj[0].innerHTML),eval(myObj[2].innerHTML))
}

function addYear(obj)  //增加年份
{
  var myObj=obj.parentNode.parentNode.parentNode.cells[2].childNodes;
  myObj[0].innerHTML=eval(myObj[0].innerHTML)+1;
  dateShow(obj.parentNode.parentNode.parentNode.nextSibling.nextSibling,eval(myObj[0].innerHTML),eval(myObj[2].innerHTML))
}

function subMonth(obj)  //减小月份
{
  var myObj=obj.parentNode.parentNode.parentNode.cells[2].childNodes;
  var month=eval(myObj[2].innerHTML)-1;
  if(month==0)
  {
    month=12;
    subYear(obj);
  }
  myObj[2].innerHTML=month;
  dateShow(obj.parentNode.parentNode.parentNode.nextSibling.nextSibling,eval(myObj[0].innerHTML),eval(myObj[2].innerHTML))
}

function addMonth(obj)  //增加月份
{
  var myObj=obj.parentNode.parentNode.parentNode.cells[2].childNodes;
  var month=eval(myObj[2].innerHTML)+1;
  if(month==13)
  {
    month=1;
    addYear(obj);
  }
  myObj[2].innerHTML=month;
  dateShow(obj.parentNode.parentNode.parentNode.nextSibling.nextSibling,eval(myObj[0].innerHTML),eval(myObj[2].innerHTML))
}

function dateShow(obj,year,month)  //显示各月份的日
{
  var myDate=new Date(year,month-1,1);
  var today=new Date();
  var day=myDate.getDay();
  var selectDate=obj.parentNode.parentNode.previousSibling.previousSibling.value.split('-');
  var length;
  switch(month)
  {
    case 1:
    case 3:
    case 5:
    case 7:
    case 8:
    case 10:
    case 12:
      length=31;
      break;
    case 4:
    case 6:
    case 9:
    case 11:
      length=30;
      break;
    case 2:
      if((year%4==0)&&(year%100!=0)||(year%400==0))
        length=29;
      else
        length=28;
  }
  for(i=0;i<obj.cells.length;i++)
  {
    obj.cells[i].innerHTML='';
    obj.cells[i].style.color='';
    obj.cells[i].className='';
  }
  for(i=0;i<length;i++)
  {
    obj.cells[i+day].innerHTML=(i+1);
    if(year==today.getFullYear()&&(month-1)==today.getMonth()&&(i+1)==today.getDate())
      obj.cells[i+day].style.color='red';
    if(year==eval(selectDate[0])&&month==eval(selectDate[1])&&(i+1)==eval(selectDate[2]))
      obj.cells[i+day].className='ds_border2';
  }
}

function getValue(obj,inputObj)  //把选择的日期传给输入框
{
  var myObj=inputObj.nextSibling.nextSibling.childNodes[0].childNodes[0].cells[2].childNodes;
  if(obj.innerHTML)
    if(obj.innerHTML.length==1&&myObj[2].innerHTML.length==1)
          inputObj.value=myObj[0].innerHTML+"-0"+myObj[2].innerHTML+"-0"+obj.innerHTML;
 else  if(obj.innerHTML.length==1&&myObj[2].innerHTML.length==2)
          inputObj.value=myObj[0].innerHTML+"-"+myObj[2].innerHTML+"-0"+obj.innerHTML;
 else  if(obj.innerHTML.length==2&&myObj[2].innerHTML.length==1)
          inputObj.value=myObj[0].innerHTML+"-0"+myObj[2].innerHTML+"-"+obj.innerHTML;
 else  if(obj.innerHTML.length==2&&myObj[2].innerHTML.length==2)
          inputObj.value=myObj[0].innerHTML+"-"+myObj[2].innerHTML+"-"+obj.innerHTML;
  inputObj.nextSibling.nextSibling.style.display='none';
  for(i=0;i<obj.parentNode.parentNode.parentNode.cells.length;i++)
    obj.parentNode.parentNode.parentNode.cells[i].className='';
  obj.className='ds_border2'
}

function dsMove(obj)  //实现层的拖移
{
  if(event.button==1)
  {
    var X=obj.clientLeft;
    var Y=obj.clientTop;
    obj.style.pixelLeft=X+(event.x-DS_x);
    obj.style.pixelTop=Y+(event.y-DS_y);
  }
}
</script>
</head>

<body>
从 
<script language=javascript>
  var myDate=new dateSelector();
  myDate.year--;
 
  myDate.inputName='start_date';  //注意这里设置输入框的name,同一页中日期输入框,不能出现重复的name。
  myDate.display();
</script>
 到 
<script language=javascript>
  myDate.year++;
  myDate.inputName='end_date';  //注意这里设置输入框的name,同一页中的日期输入框,不能出现重复的name。
  myDate.display();
</script>


</body>

</html>

posted @ 2006-03-03 16:54 joeyeezhang 阅读(252) | 评论 (0)编辑 收藏


1.错误和信息的处理.

首先在资源文件中定义错误信息和普通信息.如:MessageResources.properties中定义如下:
java代码: 


#
# Resources for testing <html:errors> tag.
#

errors.header=<table>
errors.footer=</table>
errors.prefix=<tr><td>
errors.suffix=</td></tr>

property1error1=Property 1, Error 1
property2error1=Property 2, Error 1
property2error2=Property 2, Error 2
property2error3=Property 2, Error 3
property3error1=Property 3, Error 1
property3error2=Property 3, Error 2
globalError=Global Error

#
# Resources for testing <html:messages> tag.
#

messages.header=<table>
messages.footer=</table>

property1message1=Property 1, Message 1
property2message1=Property 2, Message 1
property2message2=Property 2, Message 2
property2message3=Property 2, Message 3
property3message1=Property 3, Message 1
property3message2=Property 3, Message 2
globalMessage=Global Message



在程序中定义错误和信息类,这个例子写在JSP中

java代码: 


<%
      ActionErrors errors = new ActionErrors();
      errors.add("property1", new ActionError("property1error1"));
      errors.add("property2", new ActionError("property2error1"));
      errors.add("property2", new ActionError("property2error2"));
      errors.add("property2", new ActionError("property2error3"));
      errors.add("property3", new ActionError("property3error1"));
      errors.add("property3", new ActionError("property3error2"));
      errors.add(ActionErrors.GLOBAL_ERROR, new ActionError("globalError"));
      request.setAttribute(Globals.ERROR_KEY, errors);

      ActionMessages messages = new ActionMessages();
      messages.add("property1", new ActionMessage("property1message1"));
      messages.add("property2", new ActionMessage("property2message1"));
      messages.add("property2", new ActionMessage("property2message2"));
      messages.add("property2", new ActionMessage("property2message3"));
      messages.add("property3", new ActionMessage("property3message1"));
      messages.add("property3", new ActionMessage("property3message2"));
      messages.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("globalMessage"));
      request.setAttribute(Globals.MESSAGE_KEY, messages);
    %>





显示错误:
java代码: 


<html:errors property="property1" />
<html:errors property="property2" />


显示信息:
java代码: 


<html:messages property="property1" message="true" id="msg" header="messages.header" footer="messages.footer">
            <tr>
              <td>
                     <%= pageContext.getAttribute("msg") %>
              </td>
            </tr>
          </html:messages>

<html:messages message="true" id="msg" header="messages.header" footer="messages.footer">
            <tr>
              <td>
               <%= pageContext.getAttribute("msg") %>
              </td>
            </tr>
</html:messages>

posted @ 2006-02-13 11:04 joeyeezhang 阅读(303) | 评论 (0)编辑 收藏

线性表,链表,哈希表是常用的数据结构,在进行Java开发时,JDK已经为我们提供了一系列相应的类来实现基本的数据结构。这些类均在java.util包中。本文试图通过简单的描述,向读者阐述各个类的作用以及如何正确使用这些类。  

Collection
├List
│├LinkedList
│├ArrayList
│└Vector
│ └Stack
└Set
Map
├Hashtable
├HashMap
└WeakHashMap

Collection接口
  Collection是最基本的集合接口,一个Collection代表一组Object,即Collection的元素(Elements)。一些Collection允许相同的元素而另一些不行。一些能排序而另一些不行。Java  SDK不提供直接继承自Collection的类,Java  SDK提供的类都是继承自Collection的“子接口”如List和Set。
  所有实现Collection接口的类都必须提供两个标准的构造函数:无参数的构造函数用于创建一个空的Collection,有一个Collection参数的构造函数用于创建一个新的Collection,这个新的Collection与传入的Collection有相同的元素。后一个构造函数允许用户复制一个Collection。
  如何遍历Collection中的每一个元素?不论Collection的实际类型如何,它都支持一个iterator()的方法,该方法返回一个迭代子,使用该迭代子即可逐一访问Collection中每一个元素。典型的用法如下:
    Iterator  it  =  collection.iterator();  //  获得一个迭代子
    while(it.hasNext())  {
      Object  obj  =  it.next();  //  得到下一个元素
    }
  由Collection接口派生的两个接口是List和Set。

List接口
  List是有序的Collection,使用此接口能够精确的控制每个元素插入的位置。用户能够使用索引(元素在List中的位置,类似于数组下标)来访问List中的元素,这类似于Java的数组。
和下面要提到的Set不同,List允许有相同的元素。
  除了具有Collection接口必备的iterator()方法外,List还提供一个listIterator()方法,返回一个ListIterator接口,和标准的Iterator接口相比,ListIterator多了一些add()之类的方法,允许添加,删除,设定元素,还能向前或向后遍历。
  实现List接口的常用类有LinkedList,ArrayList,Vector和Stack。

LinkedList类
  LinkedList实现了List接口,允许null元素。此外LinkedList提供额外的get,remove,insert方法在LinkedList的首部或尾部。这些操作使LinkedList可被用作堆栈(stack),队列(queue)或双向队列(deque)。
  注意LinkedList没有同步方法。如果多个线程同时访问一个List,则必须自己实现访问同步。一种解决方法是在创建List时构造一个同步的List:
    List  list  =  Collections.synchronizedList(new  LinkedList(...));

ArrayList类
  ArrayList实现了可变大小的数组。它允许所有元素,包括null。ArrayList没有同步。
size,isEmpty,get,set方法运行时间为常数。但是add方法开销为分摊的常数,添加n个元素需要O(n)的时间。其他的方法运行时间为线性。
  每个ArrayList实例都有一个容量(Capacity),即用于存储元素的数组的大小。这个容量可随着不断添加新元素而自动增加,但是增长算法并没有定义。当需要插入大量元素时,在插入前可以调用ensureCapacity方法来增加ArrayList的容量以提高插入效率。
  和LinkedList一样,ArrayList也是非同步的(unsynchronized)。

Vector类
  Vector非常类似ArrayList,但是Vector是同步的。由Vector创建的Iterator,虽然和ArrayList创建的Iterator是同一接口,但是,因为Vector是同步的,当一个Iterator被创建而且正在被使用,另一个线程改变了Vector的状态(例如,添加或删除了一些元素),这时调用Iterator的方法时将抛出ConcurrentModificationException,因此必须捕获该异常。

Stack  类
  Stack继承自Vector,实现一个后进先出的堆栈。Stack提供5个额外的方法使得Vector得以被当作堆栈使用。基本的push和pop方法,还有peek方法得到栈顶的元素,empty方法测试堆栈是否为空,search方法检测一个元素在堆栈中的位置。Stack刚创建后是空栈。

Set接口
  Set是一种不包含重复的元素的Collection,即任意的两个元素e1和e2都有e1.equals(e2)=false,Set最多有一个null元素。
  很明显,Set的构造函数有一个约束条件,传入的Collection参数不能包含重复的元素。
  请注意:必须小心操作可变对象(Mutable  Object)。如果一个Set中的可变元素改变了自身状态导致Object.equals(Object)=true将导致一些问题。

Map接口
  请注意,Map没有继承Collection接口,Map提供key到value的映射。一个Map中不能包含相同的key,每个key只能映射一个value。Map接口提供3种集合的视图,Map的内容可以被当作一组key集合,一组value集合,或者一组key-value映射。

Hashtable类
  Hashtable继承Map接口,实现一个key-value映射的哈希表。任何非空(non-null)的对象都可作为key或者value。
  添加数据使用put(key,  value),取出数据使用get(key),这两个基本操作的时间开销为常数。
Hashtable通过initial  capacity和load  factor两个参数调整性能。通常缺省的load  factor  0.75较好地实现了时间和空间的均衡。增大load  factor可以节省空间但相应的查找时间将增大,这会影响像get和put这样的操作。
使用Hashtable的简单示例如下,将1,2,3放到Hashtable中,他们的key分别是”one”,”two”,”three”:
    Hashtable  numbers  =  new  Hashtable();
    numbers.put(“one”,  new  Integer(1));
    numbers.put(“two”,  new  Integer(2));
    numbers.put(“three”,  new  Integer(3));
  要取出一个数,比如2,用相应的key:
    Integer  n  =  (Integer)numbers.get(“two”);
    System.out.println(“two  =  ”  +  n);
  由于作为key的对象将通过计算其散列函数来确定与之对应的value的位置,因此任何作为key的对象都必须实现hashCode和equals方法。hashCode和equals方法继承自根类Object,如果你用自定义的类当作key的话,要相当小心,按照散列函数的定义,如果两个对象相同,即obj1.equals(obj2)=true,则它们的hashCode必须相同,但如果两个对象不同,则它们的hashCode不一定不同,如果两个不同对象的hashCode相同,这种现象称为冲突,冲突会导致操作哈希表的时间开销增大,所以尽量定义好的hashCode()方法,能加快哈希表的操作。
  如果相同的对象有不同的hashCode,对哈希表的操作会出现意想不到的结果(期待的get方法返回null),要避免这种问题,只需要牢记一条:要同时复写equals方法和hashCode方法,而不要只写其中一个。
  Hashtable是同步的。

HashMap类
  HashMap和Hashtable类似,不同之处在于HashMap是非同步的,并且允许null,即null  value和null  key。,但是将HashMap视为Collection时(values()方法可返回Collection),其迭代子操作时间开销和HashMap的容量成比例。因此,如果迭代操作的性能相当重要的话,不要将HashMap的初始化容量设得过高,或者load  factor过低。

WeakHashMap类
  WeakHashMap是一种改进的HashMap,它对key实行“弱引用”,如果一个key不再被外部所引用,那么该key可以被GC回收。

总结
  如果涉及到堆栈,队列等操作,应该考虑用List,对于需要快速插入,删除元素,应该使用LinkedList,如果需要快速随机访问元素,应该使用ArrayList。
  如果程序在单线程环境中,或者访问仅仅在一个线程中进行,考虑非同步的类,其效率较高,如果多个线程可能同时操作一个类,应该使用同步的类。
  要特别注意对哈希表的操作,作为key的对象要正确复写equals和hashCode方法。
  尽量返回接口而非实际的类型,如返回List而非ArrayList,这样如果以后需要将ArrayList换成LinkedList时,客户端代码不用改变。这就是针对抽象编程。
posted @ 2006-02-13 10:36 joeyeezhang 阅读(197) | 评论 (0)编辑 收藏

仅列出标题
共7页: 上一页 1 2 3 4 5 6 7 下一页