2006年6月27日

动作映射

这个时候,你可能会问自己:“当控制器接受到一个请求的时候,它如何知道调用哪个Action实例?”控制器要通过查看请求消息并使用一组动作
映射(action mapping)来做出决定。动作映射是Struts配置信息(配置一个特殊的XML文件中)的一部分。这个配置信息会在启动时加载到内存中
,让Struts框架得以在运行时加以利用。每个action元素在内存中都被表示为org.apache.struts.action.ActionMapping类的实例。
ActionMapping对象包含一个path属性,用来与外部请求的URI部分匹配。如下:
<action
    path="/login"
    type="com.oreilly.struts.banking.action.LoginAction"
    scope="request"
    name="loginForm"
    validate="true"
    input="/login.jsp"
    <forward name="Success" path="/action/getaccountinformation" redirect="true"/>
    <forward name="Failure" path="/login.jsp" redirect="true"/>
</action>
这里的登录动作映射把路径"/login"映射到了com.oreilly.struts.banking.LoginAction这个Action类。无论何时,当控制器接受到一个URI
路径中包含"/login"字符串的请求时,就会调用LoginAction实例的execute()方法。Struts框架还会使用映射来指出“动作"完成后要让用户
转向哪个资源。

 

使用Struts ActionForm

Struts框架的ActionForm对象可用来在用户和业务层之间传输客户的输入数据。Struts框架会自动从请求中收集输入数据,再将这些数据交给
一个使用表单bean(form bean)的Action对象,接着表单再交给业务层。为了把表示层和业务层分离开来,你不应该直接把ActionForm对象交
给业务层,而是应该使用由ActionForm对象得到的数据创建适当的DTO。下面的步骤说明了Struts框架如何处理每个请求相应的ActionForm对
象:
 
  1.检查该项动作的相应设置,查看是否已经有某个ActionForm得到配置。
  2.如果对应这个动作配置了某个ActionForm,则使用action元素中的name属性来查找表单bean的配置信息。
  3.查看是否已经创建了一个ActionForm的一个实例。
  4.如果在适当的作用域内已经存在一个ActionForm实例,而且这个实例的类型正是这个请求所需要的类型,则重用这个实例。
  5.否则,创建所需ActionForm的一个新实例,并存储在适当的作用域中(由action元素的scope属性设置)。
  6.调用ActionForm实例的reset()方法。
  7.反复处理请求参数,如果参数名在ActionForm实例中具有对应的设置方法(setter method),就为它填上该请求参数的值。
  8.最后,如果validate属性的值设置为true,则调用ActionForm实例的validate()方法,并返回所出现的任何错误。
对任何HTML页面而言,如果表单数据是以POST方法传输的,就应该使用ActionForm。必要时,相同的ActionForm可以同时给多个页面使用,只
要HTML字段能和ActionForm对象的属性(property)匹配就可以了。
Struts框架所提供的ActionForm类实现了多个方法,但到目前为止,最重要的两个方法就是reset()和validate():
  public void reset(ActionMapping mapping,HttpServletRequest request);
  public ActionErrors validate(ActionMapping mapping,HttpServletRequest request);
在Struts ActionForm类中,这两个方法的默认实现是不完成任何的逻辑。你必须在自己的ActionForm类中覆盖这两个方法。控制器以请求中的
值来填写ActionForm实例之前,会先调用reset()方法。reset()方法给了ActionForm一个机会,可将其属性设置为原来默认的状态。这一点非
常重要,因为表单bean实例可能会由多个请求共享或者由好几个不同的线程所存取。不过,如果你是让好几页共享一个ActionForm实例,可能
不会去想去实现reset()方法,这样一来只要这个实例还在,属性的值就不会被重新设置。另一种做法就是实现你自己的resetFields()方法,
在成功更新业务之后,就从这个Action类来调用此方法。
当请求中所携带的值已经插入到ActionFrom实例之后,控制器就回调用validate()方法。ActionForm应该对输入数据完成必要的验证工作,然
后向控制器返回所检测到的任何错误。业务逻辑验证应该在业务对象中而不是在ActionForm中来完成。在ActionForm中所进行的验证工作,只
是表示的验证而已。
一旦写好ActionForm类后,你必须通知Struts应用程序有这些ActionForm存在,告诉Struts应用程序哪个动作映射应该使用哪个ActionForm。
这是在配置文件中设置的。第一步是为你的应用程序在配置文件中的form-beans段里配置所有的ActionForm。看下面的一个例子:
 <form-beans>
    <form-bean
       name="loginForm"
       type="com.oreilly.struts.banking.form.LoginForm"/>
    <form-bean
       name="accountInformationForm"
       type="org.apache.struts.action.DynaActionForm">
       <form-property name="accounts" type="java.util.ArrayList"/>
    </form-bean>
 </form-beans>
每个表单bean的name属性必须都是独一无二的,而且其type属性必须定义一个Java类(扩展了Struts ActionForm类)的完全限定名。下一步
是在一个或多个action元素中使用在form-benas段里的某个form-bean名。如下:
  <action
    path="/login"
    type='com.oreilly.struts.banking.action.LoginAction"
    scope="request"
    name="loginForm"
    validate="true"
    input="/login.jsp">
    <forward name="Success" path="/action/getaccountinformation" redirect="ture>
    <forward name="Failure" path="/login.jsp" redirect="true"/>
  </action>
注意:登录动作映射的name正好和前面form-beans段里某个name属性相匹配。

 


 

posted @ 2006-07-05 08:07 多力宇扬 阅读(1138) | 评论 (5)编辑 收藏

美国杂志300强及其网址

No  杂志名称                                                          网址                                                    类别
1   People(人物)                             http://people.aol.com/people/index.html                     娱乐
2   TV Guide(电视指南)                 http://www.tvguide.com                                              娱乐
3   Time(时代)                                http://www.time.com                                                   新闻
4   Sports Illustrated(体育画报)   http://sportsillustrated.cnn.com 体育
5   Better Homes & Gardens(美好家园)  http://www.bhg.com 家居
6   Reader’s Digest(读者文摘)  http://www.rd.com/splash.jhtml 综合
7   Parade(旅行)  http://www.parade.com/auth/entry.lasso 旅游
8   Newsweek(新闻周刊)  http://www.msnbc.com/news/NW-front_Front.asp 新闻
9   Business Week(商业周刊)  http://www.businessweek.com 商业
10   Good Housekeeping(好主妇)  http://www.goodhousekeeping.com 家庭
11   Fortune(财富)  http://www.fortune.com/ 商业
12   Cosmopolitan(全球主义者)  http://www.cosmopolitan.com/ 娱乐
13   Woman’s Day(妇女日)  http://www.womansday.com/xp6/WomansDay/home.xml 妇女
14   Forbes(福布斯)  http://www.forbes.com/ 商业
15   Family Circle(家庭圈)  http://www.familycircle.com/home/homepage.jsp 家庭
16   USA Weekend(美国周末)  http://www.usaweekend.com 休闲
17   Instyle(时髦)  http://www.instyle.com/instyle 时尚
18   Entertainment Weekly(娱乐周刊)  http://www.ew.com/ew/ 娱乐
19   Martha Stewart Living(玛萨斯图尔特生活)   http://www.marthastewart.com 生活
20   U.S. News & World Report(美国新闻与世界报道)  http://www.usnews.com 新闻
21   Ladies’ Home Journal(妇女家庭杂志)   http://www.lhj.com 家庭
22   National Geographic(国家地理杂志)   http://www.nationalgeographic.com 地理
23   Southern Living(南方生活)  http://www.southernliving.com/ 生活
24   Vogue(时尚)  http://www.style.com/vogue/index.html 时尚
25   PC Magazine(个人电脑)  http://www.pcmag.com/ IT
26   Money(金钱)  http://money.cnn.com/ 理财
27   Maxim(马克西姆)  http://www.maximonline.com/index.html 娱乐
28   O, The Oprah Magazine   http://www.oprah.com/omagazine 妇女
29   Glamour(魅力)  http://www.glamour.com/ 时尚
30   National Enquirer, The(国家寻问者)  http://www.nationalenquirer.com/ 新闻
31   New York Times Magazine(纽约时报杂志)  http://www.nytimes.com/ 新闻
32   Golf Digest(高尔夫文摘)  http://www.golfdigest.com/ 体育
33   Rolling Stone(滚石)  http://www.rollingstone.com/ 音乐
34   Playboy(花花公子)  http://www.playboy.com/ 男性
35   Vanity Fair(名利场)  http://www.vanityfair.com 娱乐
36   Seventeen(十七岁)  http://www.seventeen.com/ 青年
37   Parents(父母)  http://www.parents.com/ 教育
38   Star Magazine(明星杂志)  http://www.starmagazine.com/ 娱乐
39   ESPN The Magazine(ESPN杂志)  http://espn.go.com/magazine/ 体育
40   Prevention(预防)  http://www.prevention.com/ 健康
41   Redbook(红书)  http://magazines.ivillage.com/redbook/ 妇女
42   Rosie   http://www.rosieo.com/ 生活
43   Golf Magazine(高尔夫杂志)  http://sportsillustrated.cnn.com/golfonline/ 体育
44   Travel & Leisure(旅游和休闲)  http://www.travelandleisure.com/ 休闲
45   Elle   http://www.elle.com/ 时尚
46   New Yorker, The(纽约客)  http://www.newyorker.com/ 文艺
47   W   http://www.style.com/w/ 时尚
48   Woman’s World(妇女世界)  http://www.robertcraig.com/womansworld.html 妇女
49   Parenting(养育)  http://www.parenting.com/parenting/ 家庭
50   Car & Driver(人车志)  http://www.caranddriver.com/xp/Caranddriver/home.xml 机车
51   Endless Vacation(无尽假日)  http://www.endlessvacation.com/ 休闲
52   Bride’s Magazine(新娘杂志)  http://www.brides.com 婚礼
53   InformationWeek(信息周刊)  http://www.informationweek.com/ IT
54   Country Living(乡村生活)  http://magazines.ivillage.com/countryliving/ 生活
55   Us Weekly(美国周刊)  http://usweekly.abc.com/ 新闻
56   Marie Claire(玛丽克莱尔)  http://www.marieclaire.com/ 时尚
57   Sunset(日落)  http://www.sunset.com/ 科学
58   Soap Opera Digest(肥皂剧文摘)  http://www.soapoperadigest.com 娱乐
59   AARP Modern Maturity(现代文明)   http://www.modernmaturity.org/ 公益
60   GQ   http://www.gq.com/ 时尚
61   Architectural Digest(建筑学文摘)  http://www.condenet.com/mags/archdigest/ 建筑
62   Harper’s Bazaar(哈泼氏)  http://www.harpersbazaar.com/ 时尚
63   Travel Agent(旅游代理)  http://www.travelagents.com/ 旅游
64   Smithsonian(史密森尼)  http://www.si.edu/ 博物
65   PC World(PC世界)  http://www.pcworld.com/ IT
66   Modern Bride(现代新娘)  http://www.modernbride.com/ 婚礼
67   Men’s Health(男性健康)  http://www.menshealth.com/ 健康
68   Bon Appetit(好 )  http://www.epicurious.com/b_ba/b00_home/ba.html 烹饪
69   Motor Trend(机车潮流)  http://www.motortrend.com/ 机车
70   Economist, The(经济学人)  http://www.economist.com/ 政经
71   Self(自我)  http://www.self.com/ 妇女
72   Shape(体形)  http://www.shapeonline.com/ 健康
73   Teen People   http://www.teenpeople.com/teenpeople/ 青年
74   YM   http://www.ym.com 时尚
75   Consumer Reports(消费者报告)  http://www.consumerreports.org/main/home.jsp 生活
76   Cooking Light(烹饪之光)  http://www.cookinglight.com/ 烹饪
77   Travel Weekly(旅行周刊)  http://www.travelweekly.co.uk/tw_home/home.asp 旅游
78   House Beautiful(美丽住宅)  http://magazines.ivillage.com/housebeautiful/ 家居
79   Ebony(乌木)  http://www.ebony.com/ 成人
80   Popular Photography(大众摄影)  http://www.popularphotography.com/index.asp 摄影
81   Country Home(乡村家庭)  http://www.countryhome.com/ch/index.html 家庭
82   Barron’s   http://www.barrons.com/ 商业
83   eWeek   http://www.eweek.com 消费
84   Conde Nast Traveler   http://www.concierge.com/cntraveler/ 旅游
85   Town & Country(城镇和乡村)   http://magazines.ivillage.com/townandcountry/ 生活
86   InfoWorld(信息世界)   http://www.infoworld.com/ IT
87   EE Times   http://www.eetimes.com/ 电子
88   Food & Wine(食物和酒)   http://www.foodandwine.com/ 食品
89   New York(纽约)   http://www.newyorkmetro.com/ 城市
90   Essence(本质)   http://www.essence.com/ 黑人
91   Road & Track(公路与轨迹)   http://www.roadandtrack.com/ 机车
92   Health(健康)   http://www.health.com/ 健康
93   Inc(公司)   http://www.inc.com/home/ 商业
94   Allure(吸引)   http://www.allure.com/ 时尚
95   Vibe   http://www.vibe.com/new/home/pointer.html 娱乐
96   Gourmet(美食家)   http://www.gourmet.com/ 烹饪
97   Taste of Home(家的滋味)   http://www.tasteofhome.com/ 烹饪
98   Muscle & Fitness(肌肉和健身)   http://www.muscleandfitness.com/ 健康
99   Popular Mechanics(大众机械)   http://popularmechanics.com/ 机械
100   Home(家)   http://www.homemag.com/ 家居
101   fitness(健身)   http://www.fitnessmagazine.com/home/index.jsp 健康
102   Field & Stream(田园和小溪)   http://www.fieldandstream.com/ 休闲
103   American Baby(美国宝贝)   http://www.americanbaby.com/ab/CDA/homepage/ 家庭
104   FamilyFun(家庭乐趣)   http://familyfun.go.com/ 家庭
105   Sporting News, The(体育新闻)   http://www.sportingnews.com/ 体育
106   Esquire(先生)   http://www.esquire.com/ 男性
107   Penthouse(小棚屋)   http://www.penthouse.com/ 成人
108   Kiplinger’s Personal Finance Magazine(吉朴林的个人金融杂志)   http://www.kiplinger.com/ 理财
109   Globe(环球)   http://www.boston.com/globe/ 环境
110   SmartMoney(精明理财)   http://www.smartmoney.com/ 理财
111   Stuff(素材)   http://www.stuffmagazine.com/ 男性
112   CRN   http://www.crn.com/ IT
113   Men’s Journal(男人)   http://www.mensjournal.com/ 男性
114   House & Garden(家园)   http://www.condenet.com/mags/hg/ 家居
115   Fast Company(快速公司)   http://www.fastcompany.com/homepage/ 商业
116   Computer Shopper(计算机购物者)   http://shopper.cnet.com/ 消费
117   Jet(黑玉)   http://www.jetmag.com/ 黑人
118   First For Women    http://www.ffwmarket.com/ 妇女
119   Traditional Home(传统家庭)   http://www.traditionalhome.com/ 家庭
120   Automobile Magazine(汽车杂志)   http://www.automobilemag.com/ 机车
121   Red Herring(红鲱鱼)   http://www.redherring.com/ 商业
122   Highlights for Children(儿童文粹)   http://www.highlights.com/ 儿童
123   Wired(连线)   http://www.wired.com/ IT
124   Outside(户外)   http://outsidemag.com/index.html 休闲
125   This Old House(这个老屋子)   http://www.thisoldhouse.com/toh/ 家居
126   NetworkWorld(网络世界)   http://www.networkworld.com/ IT
127   Entrepreneur(企业家)   http://www.entrepreneur.com/ 商业
128   Popular Science(大众科学)   http://www.popsci.com/popsci/ 科普
129   Elle Decor    http://www.elledecor.co.th/ 设计
130   Quick Cooking (速煮)   http://www.quickcooking.com/ 烹饪
131   Family Handyman(家庭佣人)   http://www.familyhandyman.com/ 家居
132   Science(科学)   http://www.sciencemag.org/ 科学
133   Bridal Guide(新娘指南)   http://www.bridalguide.com/ 婚礼
134   Child(孩子)   http://www.child.com/index.jsp 家庭
135   Cable Guide(有线电视指南)   http://www.cableguide.co.uk/ 娱乐
136   Midwest Living(中西部生活)   http://www.midwestliving.com/ 生活
137   Metropolitan Home(大城市生活)   http://www.mho.co.uk/ 生活
138   Chronicle of Higher Education, The(高等教育编年史)   http://chronicle.com/ 教育
139   Mutual Funds Magazine(互动基金杂志)  http://www.mutual-funds.com/mfmag/ 商业
140   Travelhost(旅游主人)   http://www.travelhost.com/ 旅游
141   Sound & Vision(声与影)   http://www.soundandvisionmag.com/index.asp 电影
142   CIO(首席信息官)   http://www.cio.com/ IT
143   Hot Rod    http://www.hotrod.com/ 机车
144   Computerworld(计算机世界)   http://www.computerworld.com/ IT
145   Source, The(来源)   http://www.thesource.com/ 黑人
146   Departures(启程)   http://www.departures.com/ 商业
147   Spin(旋转)   http://www.spin.com/ 音乐
148   Travel Holiday(旅行假日)   http://www.travelholiday.com/ 旅游
149   Black Enterprise(黑人企业)   http://www.blackenterprise.com/ 商业
150   BabyTalk(宝贝说话)   http://www.parenting.com/parenting/...s/babytalk.html 家庭
151   New England Journal of Medicine(新英格兰医学期刊)   http://content.nejm.org/ 医学
152   EBN Electronic Buyer’s News(EBN电子买主新闻)   http://www.ebnonline.com/ 电子
153   Jane(简)   http://www.janes.com/ 军事
154   Working Mother(妇女运动者)   http://www.workingwoman.com/ 妇女
155   Men’s Fitness(男性健身)   http://www.mensfitness.com/mens.html 健康
156   Victoria(维多利亚)   http://magazines.ivillage.com/victoria/ 生活
157   CosmoGirl(都市女孩)   http://www.cosmogirl.com/ 时尚
158   Nation’s Restaurant News(国家餐馆新闻)   http://www.nrn.com/ 行业
159   Harvard Business Review(哈佛商业评论)   http://www.hbr.com 商业
160   FHM(男人帮)   http://www.fhm.com/ 男性
161   Sports Illustrated For Kids(儿童体育画报)   http://www.sikids.com/ 儿童
162   Boating(航船)   http://www.boatingmag.com/ 体育
163   Discover(探索)   http://www.discover.com/ 科普
164   Real Simple(反朴归真)   http://www.realsimple.com/realsimple/ 生活
165   Guideposts(路标)   http://www.guideposts.com/ 宗教
166   Cycle World(环形世界)   http://www.cycleworld.com/xp6/CycleWorld/main.xml 机车
167   EDN   http://www.e-insite.net/ednmag/ 电子
168   Tennis Magazine(网球杂志)   http://www.tennis.com 体育
169   Advertising Age(广告时代)   http://www.adage.com/ 行业
170   Hemispheres(半球)   http://www.hemispheresmagazine.com/home.htm 收藏
171   Fortune Small Business(财富小商业)  http://www.fortune.com/smallbusiness/ 商业
172   Meetings & Conventions(会议)   http://www.meetings-conventions.com/ 行业
173   Worth(价值)   http://www.worth.com/magazine/index.cfm 理财
174   Outdoor Life(户外生活)   http://www.outdoorlife.com/outdoor/ 休闲
175   Official U.S. Playstation Magazine(美国官方PS杂志)  http://www.gamers.com/opm/index.jsp 游戏
176   Automotive News(汽车新闻)   http://www.autonews.com/ 机车
177   Scientific American(科学美国人)   http://www.sciam.com/ 科普
178   Nickelodeon    http://www.nick.com 娱乐
179   More(更多)   http://www.more.com 时尚
180   Ski(滑雪)   http://www.skinet.com/skinet/ 体育
181   Lucky(幸运)   http://www.luckymag.com/ 时尚
182   Interior Design(室内装饰设计)   http://www.interiordesign.net 行业
183   Sky (Delta Air Lines)(天空 三角航线)   http://www.delta-sky.com/ 航线
184   Power & Motoryacht(能源和摩托艇)   http://powerandmotoryacht.about.com/mbody.htm 休闲
185   GamePro(专业游戏)   http://www.gamepro.com/ 游戏
186   JAMA(睡衣裤)   http://jama.ama-assn.org/ 健康
187   Furniture Today(今日家具)   http://www.furnituretoday.com/index.shtml 家居
188   My Generation(我们这一代)   http://www.mygeneration.org/ 音乐
189   Successful Meetings(成功会议)   http://www.successmtgs.com/successmtgs/index.jsp 行业
190   Premiere(首映)   http://www.premiere.com 电影
191   Birds & Blooms(鸟语花香)   http://www.birdsandblooms.com/ 家居
192   Aviation Week & Space Technology(航空技术周刊)   http://www.aviationnow.com/ 休闲
193   Electronic Design(电子设计)   http://www.e-insite.net/ednmag/ 电子
194   T & L Golf(T & L高尔夫)   http://www.tlgolf.com/ 休闲
195   Wine Spectator(酒的旁观者)   http://www.winespectator.com/ 休闲
196   National Geographic Traveler(国家地理旅行者)   http://www.nationalgeographic.com/traveler/ 旅游
197   AutoWeek(汽车周刊)   http://www.autoweek.com/ 机车
198   Wood(木工)    http://www.woodmagazine.com/ 工艺
199   Chemical & Engineering News(化工新闻)   http://pubs.acs.org/cen/ 行业
200   Electronic Gaming Monthly(电子游戏月刊)   http://www.gamers.com/egm/index.jsp 游戏
201   Disney Adventures(迪斯尼冒险)   http://disney.go.com/disneyadventures/ 孩子
202   National Examiner(国家主考者)   http://www.nationalexaminer.com/ 教育
203   Soap Opera Weekly(肥皂剧周刊)   http://www.soapoperaweekly.com/ 娱乐
204   Golf World(高尔夫世界)   http://www.worldgolf.com/ 体育
205   Runner’s World(跑步者世界)   http://www.runnersworld.com/ 体育
206   Country Weekly(乡村周刊)   http://www.countryweekly.com/ 音乐
207   American Way(美国道路)   http://www.americanwaymag.com/ 旅游
208   Upside(上面)   http://www.upside.com/ IT
209   Design News (设计新闻)   http://www.manufacturing.net/ 行业
210   Details(详细资料)   http://www.condenet.com/mags/details/ 时尚
211   American Profile(美国外形)   http://www.americanprofile.com/ 健康
212   ENR   http://enr.construction.com/Default.asp 建筑
213   Machine Design(机械设计)   http://www.machinedesign.com/ 行业
214   PC Gamer(PC游戏玩家)   http://www.pcgamer.com/ 游戏
215   Biography(传记)  http://www.biography.com/ 文学
216   Atlantic Monthly(大西洋月刊)   http://www.theatlantic.com/ 文艺
217   Successful Farming(成功农业)   http://www.agriculture.com/sfonline/ 行业
218   Texas Monthly(德克莎斯月刊)   http://www.texasmonthly.com/ 地区
219   Skiing(滑雪运动)   http://www.skiingmag.com/skiing/ 体育
220   Southern Accents(南方口音)   http://www.southernaccents.com/accents/ 家庭
221   American Rifleman(美国步枪射手)   http://www.americanrifleman.org/site/index.asp 枪械
222   Bassmaster   http://www.bassmaster.com/ 休闲
223   SN-Supermarket News(超级市场新闻)   http://www.supermarketnews.com 行业
224   ABA Journal(美国银行家协会期刊)   http://www.abanet.org/journal/redesign/home.html 行业
225   Nature(自然)   http://www.nature.com/ 科学
226   Architectural Record(建筑学档案)   http://www.archrecord.com/ 行业
227   Adweek(广告周刊)   http://www.adweek.com/adweek/index.jsp 行业
228   Petersen’s 4-Wheel & Off Road   http://www.4wheeloffroad.com/ 机车
229   Business 2.0(商业2.0)   http://www.business2.com/ 商业
230   Flying(飞行)   http://www.flyingmag.com/ 休闲
231   Billboard(公告牌)   http://www.billboard.com/billboard/index.jsp 音乐
232   Coastal Living(海岸生活)   http://www.coastalliving.com/coastal/ 生活
233   Country Woman(乡村女人)   http://www.countrywomanmagazine.com/ 家庭
234   Boys’sLife(男孩生活)   http://www.boyslife.org/ 孩子
235   Transworld Skateboarding(环球滑板)  http://www.skateboarding.com/skate/ 体育
236   NFL Insider(美国足球联盟知情者)   http://ww2.nfl.com/insider/ 体育
237   People en Espanol(人物西班牙语版)   http://www.peopleenespanol.com/pespanol/index.html/ 娱乐
238   Journal of Accountancy(会计学期刊)   http://www.aicpa.org/pubs/jofa/joahome.htm 财务
239   Windows 2000 Magazine(视窗2000杂志)   http://www.win2000mag.net/ IT
240   Veranda(阳台)   http://www.veranda.com/ 家居
241   Video Business(视频商业)   http://www.videobusiness.com/ 商业
242   Backpacker(背包)   http://www.backpacker.com/ 休闲
243   Cigar Aficionado(雪茄迷)   http://www.cigaraficionado.com/ 休闲
244   Telephony(技术)   http://www.telephonyonline.com/ IT
245   Flex(弯曲)   http://www.flexonline.com/ 健康
246   Variety (weekly)(品种周刊)   http://www.variety.com/ 商业
247   Cruising World (巡航世界)   http://www.cruisingworld.com/ 休闲
248   American Hunter(美国猎人)   http://www.american-hunter.com/ 休闲
249   Crain’s Chicago Business(克瑞恩芝加哥商业)   http://www.chicagobusiness.com/ 商业
250   Broadcastin &Cable(宽带与有线电视)   http://www.broadcastingcable.com/ 行业
251   Petersen’s Photographic   http://www.photographic.com/ 摄影
252   Golf for Women(女性高尔夫)   http://www.golfdigest.com/gfw/ 体育
253   US Airways Attache Magazine  
254   Progressive Farmer(改进农场主)   http://www.progressivefarmer.com/farmer/ 农业
255   Easyriders   http://www.easyriders.com/Home/Home.asp 机车
256   Crain’s New York Business(克瑞恩纽约商业)   http://www.crainsny.com/ 商业
257   Yachting(游艇)   http://www.yachtingnet.com/yachting/ 休闲
258   Chicago(芝加哥)   http://www.chicagomag.com/ 城市
259   Computer Gaming World(计算机游戏世界)   http://www.gamers.com/cgw/index.jsp 游戏
260   Video Store(视频商店)   http://www.videostoremag.com/ 商业
261   Country(乡村)    http://www.country-magazine.com/ 生活
262   Fine Homebuilding(好家建造者)   http://www.taunton.com/finehomebuilding/index.asp 家居
263   Yankee(美国佬)   http://www.yankeemagazine.com/travel/index.php 旅游
264   Publisher’s Weekly(出版者周刊)   http://www.publishersweekly.com/ 行业
265   Restaurants & Institutions(餐馆与协会)   http://www.rimag.com/ 行业
266   American Medical News(美国医学新闻)   http://www.ama-assn.org/public/journals/amnews/ 行业
267   North American Hunter(北美猎人)   http://visitors.huntingclub.com/magazine.asp 休闲
268   Federal Computer Week(联邦计算机周刊)   http://www.fcw.com/ IT
269   Guns & Ammo(枪与军火)   http://www.gunsandammomag.com/dynamic.asp 枪械
270   Transworld Snowboarding(环球滑雪板)  http://www.snowboarding-online.com/ 体育
271   New Equipment Digest(新设备文摘)   http://www.newequipment.com/ 行业
272   Weekly World News(世界新闻周刊)    http://www.weeklyworldnews.com/ 新闻
273   Chemical Week(化学周刊)   http://www.chemweek.com/ 行业
274   Four Wheeler(四轮车)   http://www.fourwheeler.com/ 机车
275   Gear(齿轮)    http://www.gearmagazine.com/ 家居
276   Pensions & Investments(养老金和投资)   http://www.pionline.com/ 理财
277   Macworld(Mac世界)    http://www.macworld.com/ IT
278   Builder(建筑者)    http://builder.com.com/ IT
279   RB Restaurant Business(餐馆业)    http://www.foodservicetoday.com/rb/index.shtml 行业
280   CFO(首席运营官)    http://www.cfo.com/ IT
281   American Family Physician(美国家庭医生)   http://www.aafp.org/afp.xml 健康
282   Los Angeles Times Magazine(洛杉矶时报杂志)   http://www.latimes.com/ 新闻
283   Saveur    http://www.saveur.com 烹饪
284   Multichannel News(多频道新闻)   http://www.multichannel.com/ 行业
285   Purchasing(购买)    http://www.manufacturing.net/ 消费
286   Laser Focus World(激光焦点世界)   http://lfw.pennnet.com/home.cfm 行业
287   HANDY(手工)   http://visitors.handymanclub.com/handy_mag.asp 家居
288   Medical Economics(医药经济)   http://www.medec.com/ 行业
289   Reminisce(回忆)   http://www.reminisce.com/ 休闲
290   Pillsbury Classic Cookbooks   http://www.pillsbury.com/ 烹饪
291   Skin Diver(滑水)   http://www.skin-diver.com/ 休闲
292   Nursing 2002   http://www.nursinghomesmagazine.com/ 护理
293   Hemmings Motor News   http://cars.hemmings.com/ 机车
294   American Legion Magazine(美国军团杂志)   http://www.legion.org/ 公益
295   Farm Journal(农业期刊)   http://www.farmjournal.com/ 农业
296   Southwest Airlines Spirit(西南航线精灵)   http://www.spiritmag.com/ 航行
297   Dr. Dobb’s Journal   http://www.ddj.com/ IT
298   Chicago Tribune Magazine(芝加哥论坛杂志)   http://www.chicagotribune.com/features/magazine/ 新闻
299   Islands(岛屿)   http://www.islands.com/ 休闲
300   Institutional Investor(金融机构投资者)   http://www.epinions.com 金融

posted @ 2006-07-05 08:05 多力宇扬 阅读(494) | 评论 (0)编辑 收藏

Ant是什么?
Ant是一种基于Java的build工具。理论上来说,它有些类似于(Unix)C中的make ,但没有make的缺陷。

既然我们已经有了make, gnumake, nmake, jam以及其他的build工具为什么还要要一种新的build工具呢?因为Ant的原作者在多种(硬件)平台上开发软件时,无法忍受这些工具的限制和不便。类似于make的工具本质上是基于shell(语言)的:他们计算依赖关系,然后执行命令(这些命令与你在命令行敲的命令没太大区别)。这就意味着你可以很容易地通过使用OS特有的或编写新的(命令)程序扩展该工具;然而,这也意味着你将自己限制在了特定的OS,或特定的OS类型上,如Unix。

Makefile也很可恶。任何使用过他们的人都碰到过可恶的tab问题。Ant的原作者经常这样问自己:“是否我的命令不执行只是因为在我的tab前有一个空格?!!”。类似于jam的工具很好地处理了这类问题,但是(用户)必须记住和使用一种新的格式。

Ant就不同了。与基于shell命令的扩展模式不同,Ant用Java的类来扩展。(用户)不必编写shell命令,配置文件是基于XML的,通过调用target树,就可执行各种task。每个task由实现了一个实现了特定Task接口的对象来运行。(如果你对Ant一点概念都没有的话,可能看不懂这一节,没有关系,后面会对target,task做详细的介绍。你如果没有太多的时间甚至可以略过这一节,然后再回来浏览一下这里的介绍,那时你就会看懂了。同样,如果你对make之类的工具不熟悉也没关系,下面的介绍根本不会用到make中的概念。)

必须承认,这样做,在构造shell命令时会失去一些特有的表达能力。如`find . -name foo -exec rm {}`,但却给了你跨平台的能力-你可以在任何地方工作。如果你真的需要执行一些shell命令,Ant有一个<exec> task,这个task允许执行特定OS上的命令。

安装Ant
由于Ant是一个Open Source的软件,所以有两种安装Ant的方式,一种是用已编译好的binary 文件安装Ant,另一种是用源代码自己build Ant。

binary 形式的Ant可以从http://jakarta.apache.org/builds/ant/release/v1.4.1/bin下载。如果你希望你能自己编译Ant,则可从 http://jakarta.apache.org/builds/ant/release/v1.4.1/src。注意所列出的连接都是最新发行版的Ant。如果你读到此文时,发现已经有了更新的版本,那么请用新版本。如果你是一个疯狂的技术追求者,你也可以从Ant CVS repository下载最新版本的Ant。

系统需求

要想自己build Ant。你需要一个JAXP兼容的XML解析器(parser)放在你的CLASSPATH系统变量中。

binary 形式的Ant包括最新版的Apache Crimson XML解析器。你可以从http://java.sun.com/xml/ 得到更多的关于JAXP的信息。如果你希望使用其他的JAXP兼容的解析器。你要从Ant的lib目录中删掉jaxp.jar以及crimson.jar。然后你可将你心爱的解析器的jar文件放到Ant的lib目录中或放在你的CLASSPATH系统变量中。

对于当前版本的Ant,需要你的系统中有JDK,1.1版或更高。未来的Ant版本会要求使用JDK 1.2或更高版本。

binary 版的Ant包括三个目录:bin, docs 和lib。只有bin和lib目录是运行Ant所需的。要想安装Ant,选择一个目录并将发行版的文件拷贝到该目录下。这个目录被称作ANT_HOME。

在你运行Ant之前需要做一些配置工作。

将bin目录加入PATH环境变量。
设定ANT_HOME环境变量,指向你安装Ant的目录。在一些OS上,Ant的脚本可以猜测ANT_HOME(Unix和Windos NT/2000)-但最好不要依赖这一特性。
可选地,设定JAVA_HOME环境变量(参考下面的高级小节),该变量应该指向你安装JDK的目录。

注意:不要将Ant的ant.jar文件放到JDK/JRE的lib/ext目录下。Ant是个应用程序,而lib/ext目录是为JDK扩展使用的(如JCE,JSSE扩展)。而且通过扩展装入的类会有安全方面的限制。

可选Task

Ant支持一些可选task。一个可选task一般需要额外的库才能工作。可选task与Ant的内置task分开,单独打包。这个可选包可以从你下载Ant的同一个地方下载。目前包含可选task的jar文件名叫jakarta-ant-1.4.1-optional.jar。这个jar文件应该放到Ant安装目录的lib目录下。

每个可选task所需的外部库可参看依赖库小节。这些外部库可以放到Ant的lib目录下,这样Ant就能自动装入,或者将其放入环境变量中。

Windows

假定Ant安装在c:\ant\目录下。下面是设定环境的命令:

set ANT_HOME=c:\ant
set JAVA_HOME=c:\jdk1.2.2
set PATH=%PATH%;%ANT_HOME%\bin
Unix (bash)

假定Ant安装在/usr/local/ant目录下。下面是设定环境的命令:

export ANT_HOME=/usr/local/ant
export JAVA_HOME=/usr/local/jdk-1.2.2
export PATH=${PATH}:${ANT_HOME}/bin
高级

要想运行Ant必须使用很多的变量。你至少参考需要下面的内容:

Ant的CLASSPATH必须包含ant.jar以及你所选的JAXP兼容的XML解析器的jar文件。
当你需要JDK的功能(如javac或rmic task)时,对于JDK 1.1,JDK的classes.zip文件必须放入CLASSPATH中;对于JDK 1.2或JDK 1.3,则必须加入tools.jar。如果设定了正确的JAVA_HOME环境变量,Ant所带的脚本,在bin目录下,会自动加入所需的JDK类。
当你执行特定平台的程序(如exec task或cvs task)时,必须设定ant.home属性指向Ant的安装目录。同样,Ant所带的脚本利用ANT_HOME环境变量自动设置该属性。
Building Ant

要想从源代码build Ant,你要先安装Ant源代码发行版或从CVS中checkout jakarta-ant模块。

安装好源代码后,进入安装目录。

设定JAVA_HOME环境变量指向JDK的安装目录。要想知道怎么做请参看安装Ant小节。

确保你已下载了任何辅助jar文件,以便build你所感兴趣的task。这些jar文件可以放在CLASSPATH中,也可以放在lib/optional目录下。参看依赖库小节可知不同的task需要那些jar文件。注意这些jar文件只是用作build Ant之用。要想运行Ant,你还要像安装Ant小节中所做的那样设定这些jar文件。

现在你可以build Ant了:

build -Ddist.dir=<directory_to_contain_Ant_distribution> dist (Windows)
build.sh -Ddist.dir=<directory_to_contain_Ant_distribution> dist (Unix)

这样就可你指定的目录中创建一个binary版本。

上面的命令执行下面的动作:

如果有必要可以bootstrap Ant的代码。bootstrap 包括手工编辑一些Ant代码以便运行Ant。bootstrap 用于下面的build步骤。
向build脚本传递参数以调用bootstrap Ant。参数定义了Ant的属性值并指定了Ant自己的build.xml文件的"dist" target。

大多数情况下,你不必直接bootstrap Ant,因为build脚本为你完成这一切。运行bootstrap.bat (Windows) 或 bootstrap.sh (UNIX) 可以build一个新的bootstrap版Ant。


如果你希望将Ant安装到ANT_HOME目录下,你可以使用:

build install (Windows)
build.sh install (Unix)

如果你希望跳过冗长的Javadoc步骤,可以用:

build install-lite (Windows)
build.sh install-lite (Unix)

这样就只会安装bin和lib目录。

注意install和install-lite都会覆盖ANT_HOME中的当前Ant版本。

依赖库

如果你需要执行特定的task,你需要将对应的库放入CLASSPATH或放到Ant安装目录的lib目录下。注意使用mapper时只需要一个regexp库。同时,你也要安装Ant的可选jar包,它包含了task的定义。参考上面的安装Ant小节。

Jar Name Needed For Available At
An XSL transformer like Xalan or XSL:P style task http://xml.apache.org/xalan-j/index.html or http://www.clc-marketing.com/xslp/
jakarta-regexp-1.2.jar regexp type with mappers jakarta.apache.org/regexp/
jakarta-oro-2.0.1.jar regexp type with mappers and the perforce tasks jakarta.apache.org/oro/
junit.jar junit tasks www.junit.org
stylebook.jar stylebook task CVS repository of xml.apache.org
testlet.jar test task java.apache.org/framework
antlr.jar antlr task www.antlr.org
bsf.jar script task oss.software.ibm.com/developerworks/projects/bsf
netrexx.jar netrexx task www2.hursley.ibm.com/netrexx
rhino.jar javascript with script task www.mozilla.org
jpython.jar python with script task www.jpython.org
netcomponents.jar ftp and telnet tasks www.savarese.org/oro/downloads

运行Ant
运行Ant非常简单,当你正确地安装Ant后,只要输入ant就可以了。

没有指定任何参数时,Ant会在当前目录下查询build.xml文件。如果找到了就用该文件作为buildfile。如果你用 -find 选项。Ant就会在上级目录中寻找buildfile,直至到达文件系统的根。要想让Ant使用其他的buildfile,可以用参数 -buildfile file,这里file指定了你想使用的buildfile。

你也可以设定一些属性,以覆盖buildfile中指定的属性值(参看property task)。可以用 -Dproperty=value 选项,这里property是指属性的名称,而value则是指属性的值。也可以用这种办法来指定一些环境变量的值。你也可以用property task来存取环境变量。只要将 -DMYVAR=%MYVAR% (Windows) 或 -DMYVAR=$MYVAR (Unix) 传递给Ant -你就可以在你的buildfile中用${MYVAR}来存取这些环境变量。

还有两个选项 -quite,告诉Ant运行时只输出少量的必要信息。而 -verbose,告诉Ant运行时要输出更多的信息。

可以指定执行一个或多个target。当省略target时,Ant使用标签<project>的default属性所指定的target。

如果有的话,-projecthelp 选项输出项目的描述信息和项目target的列表。先列出那些有描述的,然后是没有描述的target。

命令行选项总结:

ant [options] [target [target2 [target3] ...]]
Options:
-help print this message
-projecthelp print project help information
-version print the version information and exit
-quiet be extra quiet
-verbose be extra verbose
-debug print debugging information
-emacs produce logging information without adornments
-logfile file use given file for log output
-logger classname the class that is to perform logging
-listener classname add an instance of class as a project listener
-buildfile file use specified buildfile
-find file search for buildfile towards the root of the filesystem and use the first one found
-Dproperty=value set property to value
例子

ant

使用当前目录下的build.xml运行Ant,执行缺省的target。

ant -buildfile test.xml

使用当前目录下的test.xml运行Ant,执行缺省的target。

ant -buildfile test.xml dist

使用当前目录下的test.xml运行Ant,执行一个叫做dist的target。

ant -buildfile test.xml -Dbuild=build/classes dist

使用当前目录下的test.xml运行Ant,执行一个叫做dist的target,并设定build属性的值为build/classes。

文件

在Unix上,Ant的执行脚本在做任何事之前都会source(读并计算值)~/.antrc 文件;在Windows上,Ant的批处理文件会在开始时调用%HOME%\antrc_pre.bat,在结束时调用%HOME%\antrc_post.bat。你可以用这些文件配置或取消一些只有在运行Ant时才需要的环境变量。看下面的例子。

环境变量

包裹脚本(wrapper scripts)使用下面的环境变量(如果有的话):

JAVACMD Java可执行文件的绝对路径。用这个值可以指定一个不同于JAVA_HOME/bin/java(.exe)的JVM。
ANT_OPTS 传递给JVM的命令行变量-例如,你可以定义属性或设定Java堆的最大值

手工运行Ant

如果你自己动手安装(DIY)Ant,你可以用下面的命令启动Ant:

java -Dant.home=c:\ant org.apache.tools.ant.Main [options] [target]

这个命令与前面的ant命令一样。选项和target也和用ant命令时一样。这个例子假定你的CLASSPATH包含:

ant.jar

jars/classes for your XML parser

the JDK's required jar/zip files

编写build.xml
Ant的buildfile是用XML写的。每个buildfile含有一个project。

buildfile中每个task元素可以有一个id属性,可以用这个id值引用指定的任务。这个值必须是唯一的。(详情请参考下面的Task小节)

Projects

project有下面的属性:

Attribute Description Required
name 项目名称. No
default 当没有指定target时使用的缺省target Yes
basedir 用于计算所有其他路径的基路径。该属性可以被basedir property覆盖。当覆盖时,该属性被忽略。如果属性和basedir property都没有设定,就使用buildfile文件的父目录。 No

项目的描述以一个顶级的<description>元素的形式出现(参看description小节)。

一个项目可以定义一个或多个target。一个target是一系列你想要执行的。执行Ant时,你可以选择执行那个target。当没有给定target时,使用project的default属性所确定的target。

Targets

一个target可以依赖于其他的target。例如,你可能会有一个target用于编译程序,一个target用于生成可执行文件。你在生成可执行文件之前必须先编译通过,所以生成可执行文件的target依赖于编译target。Ant会处理这种依赖关系。

然而,应当注意到,Ant的depends属性只指定了target应该被执行的顺序-如果被依赖的target无法运行,这种depends对于指定了依赖关系的target就没有影响。

Ant会依照depends属性中target出现的顺序(从左到右)依次执行每个target。然而,要记住的是只要某个target依赖于一个target,后者就会被先执行。

<target name="A"/>
<target name="B" depends="A"/>
<target name="C" depends="B"/>
<target name="D" depends="C,B,A"/>

假定我们要执行target D。从它的依赖属性来看,你可能认为先执行C,然后B,最后A被执行。错了,C依赖于B,B依赖于A,所以先执行A,然后B,然后C,最后D被执行。

一个target只能被执行一次,即时有多个target依赖于它(看上面的例子)。

如果(或如果不)某些属性被设定,才执行某个target。这样,允许根据系统的状态(java version, OS, 命令行属性定义等等)来更好地控制build的过程。要想让一个target这样做,你就应该在target元素中,加入if(或unless)属性,带上target因该有所判断的属性。例如:

<target name="build-module-A" if="module-A-present"/>
<target name="build-own-fake-module-A" unless="module-A-present"/>

如果没有if或unless属性,target总会被执行。

可选的description属性可用来提供关于target的一行描述,这些描述可由-projecthelp命令行选项输出。

将你的tstamp task在一个所谓的初始化target是很好的做法,其他的target依赖这个初始化target。要确保初始化target是出现在其他target依赖表中的第一个target。在本手册中大多数的初始化target的名字是"init"。

target有下面的属性:

Attribute Description Required
name target的名字 Yes
depends 用逗号分隔的target的名字列表,也就是依赖表。 No
if 执行target所需要设定的属性名。 No
unless 执行target需要清除设定的属性名。 No
description 关于target功能的简短描述。 No

Tasks

一个task是一段可执行的代码。

一个task可以有多个属性(如果你愿意的话,可以将其称之为变量)。属性只可能包含对property的引用。这些引用会在task执行前被解析。

下面是Task的一般构造形式:

<name attribute1="value1" attribute2="value2" ... />

这里name是task的名字,attributeN是属性名,valueN是属性值。

有一套内置的(built-in)task,以及一些可选task,但你也可以编写自己的task。

所有的task都有一个task名字属性。Ant用属性值来产生日志信息。

可以给task赋一个id属性:

<taskname id="taskID" ... />

这里taskname是task的名字,而taskID是这个task的唯一标识符。通过这个标识符,你可以在脚本中引用相应的task。例如,在脚本中你可以这样:

<script ... >
task1.setFoo("bar");
</script>

设定某个task实例的foo属性。在另一个task中(用java编写),你可以利用下面的语句存取相应的实例。

project.getReference("task1").

注意1:如果task1还没有运行,就不会被生效(例如:不设定属性),如果你在随后配置它,你所作的一切都会被覆盖。

注意2:未来的Ant版本可能不会兼容这里所提的属性,因为很有可能根本没有task实例,只有proxies。

Properties

一个project可以有很多的properties。可以在buildfile中用property task来设定,或在Ant之外设定。一个property有一个名字和一个值。property可用于task的属性值。这是通过将属性名放在"${"和"}"之间并放在属性值的位置来实现的。例如如果有一个property builddir的值是"build",这个property就可用于属性值:${builddir}/classes。这个值就可被解析为build/classes。

内置属性

如果你使用了<property> task 定义了所有的系统属性,Ant允许你使用这些属性。例如,${os.name}对应操作系统的名字。

要想得到系统属性的列表可参考the Javadoc of System.getProperties。

除了Java的系统属性,Ant还定义了一些自己的内置属性:
basedir project基目录的绝对路径 (与<project>的basedir属性一样)。
ant.file buildfile的绝对路径。
ant.version Ant的版本。
ant.project.name 当前执行的project的名字;由<project>的name属性设定.
ant.java.version Ant检测到的JVM的版本; 目前的值有"1.1", "1.2", "1.3" and "1.4".
例子:
<?xml version="1.0" encoding="GB2312"?>

 <project name="MyApp" default="compile" basedir=".">
 <!--定义你需要的属性-->
  <property environment="env" />
  <property name="src" value="WEB-INF/src" />
  <property name="classes" value="WEB-INF/classes" />
  <property name="lib" value="WEB-INF/lib" />
  <property name="dist" value="dist" />
 
  <path id="task.classpath">
    <pathelement location="${classes}" />
    <pathelement location="${lib}" />
   
    <!-- Tomcat 5.0.16 Servlet 2.4 API -->
    <pathelement location="${lib}/servlet-api.jar" />
   
    <!-- Tomcat 5.0.16 JSP 2.0 API -->
    <pathelement location="${lib}/jsp-api.jar" />
   
  </path>
 
<!--定义操作--> 
  <target name="init" >
    <echo>初始化完成!</echo>
    <echo>ant home = ${ant.home} </echo>
    <echo>java home = ${java.home} </echo>
    <echo>user home = ${user.home} </echo>       
      
  </target>
 
<!--depends定义依赖-->
  <target name="compile" depends="init" >
    <javac classpathref="task.classpath" srcdir="${src}" destdir="${classes}" />
    <echo level="verbose">Seen with -verbose</echo>
    <echo level="debug">Seen with -debug</echo>       
    <echo>编译完成!</echo>
  </target>
 
  <target name="war" >
    <jar jarfile="${dist}/MyApp.war" basedir="."/>
  </target>

</project>

Token Filters
一个project可以有很多tokens,这些tokens在文件拷贝时会被自动扩展,这要求在支持这一行为的task中选择过滤拷贝功能。这一功能可用filter task在buildfile中设定。

既然这很可能是一个有危害的行为,文件中的tokens必须采取@token@的形式,这里token是filter task中设定的token名。这种token语法与其他build系统执行类似filtering的语法相同,而且与大多数的编程和脚本语言以及文档系统并不冲突,

注意:如果在一个文件中发现了一个@token@形式的token,但没有filter与这个token关连,则不会发生任何事;因此,没有转义方法-但只要你为token选择合适的名字,就不会产生问题。

警告:如果你在拷贝binary文件时打开filtering功能,你有可能破坏文件。这个功能只针对文本文件。

Path-like Structures
你可以用":"和";"作为分隔符,指定类似PATH和CLASSPATH的引用。Ant会把分隔符转换为当前系统所用的分隔符。

当需要指定类似路径的值时,可以使用嵌套元素。一般的形式是

<classpath>
<pathelement path="${classpath}"/>
<pathelement location="lib/helper.jar"/>
</classpath>
location属性指定了相对于project基目录的一个文件和目录,而path属性接受逗号或分号分隔的一个位置列表。path属性一般用作预定义的路径--其他情况下,应该用多个location属性。

为简洁起见,classpath标签支持自己的path和location属性。所以:

<classpath>
<pathelement path="${classpath}"/>
</classpath>
可以被简写作:

<classpath path="${classpath}"/>
也可通过<fileset>元素指定路径。构成一个fileset的多个文件加入path-like structure的顺序是未定的。

<classpath>
<pathelement path="${classpath}"/>
<fileset dir="lib">
<include name="**/*.jar"/>
</fileset>
<pathelement location="classes"/>
</classpath>
上面的例子构造了一个路径值包括:${classpath}的路径,跟着lib目录下的所有jar文件,接着是classes目录。

如果你想在多个task中使用相同的path-like structure,你可以用<path>元素定义他们(与target同级),然后通过id属性引用--参考Referencs例子。

path-like structure可能包括对另一个path-like structurede的引用(通过嵌套<path>元素):

<path id="base.path">
<pathelement path="${classpath}"/>
<fileset dir="lib">
<include name="**/*.jar"/>
</fileset>
<pathelement location="classes"/>
</path>
<path id="tests.path">
<path refid="base.path"/>
<pathelement location="testclasses"/>
</path>

前面所提的关于<classpath>的简洁写法对于<path>也是有效的,如:

<path id="tests.path">
  <path refid="base.path"/>
<pathelement location="testclasses"/>
</path>
可写成:

<path id="base.path" path="${classpath}"/>
命令行变量

有些task可接受参数,并将其传递给另一个进程。为了能在变量中包含空格字符,可使用嵌套的arg元素。

Attribute Description Required
value 一个命令行变量;可包含空格字符。 只能用一个
line 空格分隔的命令行变量列表。
file 作为命令行变量的文件名;会被文件的绝对名替代。
path 一个作为单个命令行变量的path-like的字符串;或作为分隔符,Ant会将其转变为特定平台的分隔符。

例子

<arg value="-l -a"/>
是一个含有空格的单个的命令行变量。

<arg line="-l -a"/>
是两个空格分隔的命令行变量。

<arg path="/dir;/dir2:\dir3"/>
是一个命令行变量,其值在DOS系统上为\dir;\dir2;\dir3;在Unix系统上为/dir:/dir2:/dir3 。

References

buildfile元素的id属性可用来引用这些元素。如果你需要一遍遍的复制相同的XML代码块,这一属性就很有用--如多次使用<classpath>结构。

下面的例子:

<project ... >
<target ... >    
<rmic ...>      
<classpath>        
<pathelement location="lib/"/>        
<pathelement path="${java.class.path}/"/>        
<pathelement path="${additional.path}"/>      
</classpath>    
</rmic>  
</target>
<target ... >
<javac ...>
<classpath>
<pathelement location="lib/"/>
<pathelement path="${java.class.path}/"/>
<pathelement path="${additional.path}"/>
</classpath>
</javac>
</target>
</project>
可以写成如下形式:

<project ... >
<path id="project.class.path">  
<pathelement location="lib/"/>
<pathelement path="${java.class.path}/"/>  
<pathelement path="${additional.path}"/>
</path>
<target ... >
<rmic ...>
<classpath refid="project.class.path"/>
</rmic>
</target>
<target ... >
<javac ...>
<classpath refid="project.class.path"/>
</javac>
</target>
</project>
所有使用PatternSets, FileSets 或 path-like structures嵌套元素的task也接受这种类型的引用

posted @ 2006-07-04 14:44 多力宇扬 阅读(313) | 评论 (0)编辑 收藏

JavaServer Pages Standard Tag Libray(1.1),其中文名字为JSP标准标签函数库。JSTL是一个标准的已
制定好的标签库,可以应用于各种领域,如:基本输入输出,流程控制,循环,XML文件剖析,数据库查
询以及国际化和文字格式标准化的应用等。JSTL所提供的标签库分为以下五大类:
 核心标签库(Core tag Liabry)
 I18N格式标签库(I18N-capable formatting tag libary)
 SQL标签库(SQL tag Libary)
 XML标签库(XML tag Libary)
 函数标签库(Functions tag Libary)

核心标签库(Core tag Liabry)主要有:基本输入输出,流程控制,迭代操作和URL操作。
 ----------------------------------------------------------------------------
      分类            功能分类                 标签分类
                                                             out
                                                              set
                          表达式操作                     remove
                                                                   catch
  
     Core                                                      if
                                                                   choose
                           流程控制                            when
                                                                       outherwise

                                                                    forEach
                              迭代操作                      forTokens

                                                                       import
                                                                          param
                                                                       url
                                 URL操作                          param
                                                                     redirect
                                                                           param
------------------------------------------------------------------------------------------
在JSP中使用JSTL中的标签库时,必须使用<%@taglib%>指令,并且设定prefix和uri的值得,通常设定:
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
这样就可以使用核心标签库了。

.表达式操作
 表达式操作分类中包含四个标签: <c:out>,<c:set>,<c:remove>和<c:catch>
<c:out>:重要用来显示数据的内容,类似与<%=scripting-language%>。它的语法如下:
语法1: 没有body内容
<c:out value="value" [escapeXml="{true|false}"] [default="defaultValue"]/>

语法2: 有body内容
<c:out value="value"  [escapeXml="{true|false}"]>
  default value
</c:out>

Attribute
-----------------------------------------------------------------------------------------------------------------------
 名称                      说明                                                               EL     类型     必须       默认值
value                  需要显示的值                                                     Y      Object    是          无
default               如果value值为null,则显示default的值                  Y      Object    否          无
escapeXml        是否转换特殊字符,如: <转换为&It                 Y      Object    否          true
----------------------------------------------------------------------------------------------------------------------
Null和错误说明
假若value为null,会显示default的值;假若没有设定default的值,则会显示一个空的字符串。

<c:set>:主要用来把变量存储至JSP范围或是JavaBean的属性中。
语法1: 没有body
将value的值存储至范围为scope的varName变量之中
<c:set value="value" var="varName" [scope="{page|request|session|application}"]/>

语法2: 有body
将body内容存储至范围为scope的varName变量之中
<c:set value="value" [scope="{page|request|session|application}"]>
  body.....
</c:set>

语法3: 将value的值存储至target对象属性中
<c:set value="value" target="target" property="propertyNmae"/>

语法4: 将body内容的数据存储至target对象属性中
<c:set target="target" property="propertyNmae">
 body....
</c:set>

Attribute
----------------------------------------------------------------------------------------
 名称                    说明                                              EL     类型      必须      默认值
value             要被存储的值                                      Y      Object      否          无
var                欲存入的变量名                                  N      String        否          无
scope            var变量的JSP范围                               N      String        否         page
target            为一JavaBean或java.util.Map对象        Y      Object       否          无
property        指定target对象属性                              Y      String        否          无
------------------------------------------------------------------------------------------
Null 和 错误处理:
语法3和语法4会产生异常错误,有以下两种情况:
 .target 为null
 .target 不是java.util.Map或JavaBean对象
假若value为null时:将由存储变量改为移除变量
 .语法1: 由var和scope所定义的变量,将被移除
    .若scope已指定时,则PageContext.removeAttribute(varName,scope);
    .若scope未指定时,则PageContext.removeAttribute(varName);
 .语法3:
    .假若target为Map时,则Map.remove(property);
    .假若target为JavaBean时,propertye指定的属性为null
注意: var和scope这两个属性不能使用表达式来表示,我们不能写成 scope="${ourScope}"或var="${a}"

<c:remove>:主要用来移除变量。
语法:
<c:remove var="varName" [scope="{page|request|session|application}"]/>

Attribute
----------------------------------------------------------------------------------------
 名称                 说明                                     EL     类型     必须       默认值
 var             欲移除变量的名称                     N      String     是              无
 scope           var变量的JSP范围                    N      String     否             page
----------------------------------------------------------------------------------------
说明:
<c:remove>必须要有var属性,即要被移除的属性名称,scope则可有可无,如:
<c:remove var="username" scope="session"/>
将username变量从session范围移除。若我们不设定scope,则<c:remove>会移除所有范围名称为username
的数据。

<c:catch>:主要用来处理产生错误的异常情况,并且将信息保存起来。
语法:
<c:catch [var="varName"]>
 ...欲抓取错误的部分...
</c:catch>

Attribute
----------------------------------------------------------------------------------------
 名称                 说明                                           EL     类型     必须       默认值
 var           用来存储错误信息的变量                 N      String       否          无
-----------------------------------------------------------------------------------------
说明:
<c:catch>主要将可能发生错误的部分放在<c:catch>和</c:catch>之间。如果真的发生错误,可将错误
信息保存至变量varName标量中,如:
<c:catch var="message">
    //可能发生错误的部分
</catch>
另外,当错误发生<c:catch>和</c:catch>之间时,只有<c:catch>和</c:catch>之间的程序会被中止忽
略,但整个网页不会被中止。

流程控制
流程控制分类中包含四个标签:<c:if>,<c:choose>,<c:when>和<c:otherwise>。

<c:if>:的用途和我们在一般程序中写的if一样。
语法:
语法1:没有body
<c:if test="testCondition" var="varName" [scope="{page|request|session|application}"]/>

语法2: 有body
<c:if test="testCondition" [var="varName"] [scope="{page|request|session|appliation}"]>
  ...body....
</c:if>

Attribute
------------------------------------------------------------------------------------------------------------------------
 名称                           说明                                                                           EL     类型        必须       默认值
test                   如果表达式的结果为true则执行body,false则相反              Y      boolean       是           无
var                   用来存储test运算后的结果,即true或false                           N     String          否           无
scope               var变量的JSP范围                                                                  N     String          否          page
------------------------------------------------------------------------------------------------------------------------
说明:
<c:if>标签必须要有test属性,body里除了能是静态文本之外可以是任何JSP代码,标签或HTML代码。

<c:choose>:本身只当作<c:when>和<c:otherwise>的父标签。
语法:
<c:choose>
  body(<when>和<otherwise>)
</c:choose>
限制:
<c:choose>的本地内容只能有:
 .空白
 .1或多个<c:when>
 .0或多个<c:otherwise>
如:
<c:choose>

 <c:when test="${condition1}">
   condition1 为 true
 </c:when>

 <c:when test="${condition2}">
   condition2 为 true
 </c:when>

 <c:otherwise>
   condition1和conditon2都为false
 </<c:otherwise >
 
</c:choose>
说明:
在同一个<c:choose>中,假如所有的<c:when>的test都不为true时,则执行<c:otherwise>的本体内容。
在同一个<c:choose>中,假若有好几个<c:when>都会true时,只能有一个<c:when>成立。

迭代操作
迭代(Iterator)操作主要包含两个标签: <c:forEach>和<c:forTokens>。

<c:forEach>为循环控制,它可以将集合(Collection)中的成员循序浏览一遍。运做方式为当条件符合
时,就会持续重复执行<c:forEach>的body内容。
语法:
语法1: 迭代一集合对象之所有成员
<c:forEach [var="varName"] items="collection" [varStatus="varStatusName"]
           [begin="begin"] [end="end"] [step="step"]>
 ...body内容.....
<c:forEach>

语法2: 迭代指定的次数
<c:forEach [var="varName"] [varStatus="varStatusName"]
           begin="begin" end="end" [step="step"]>
 ...body内容.....
<c:forEach>

Attribute
--------------------------------------------------------------------------------------------------------------------------
 名称                 说明                                                   EL     类型             必须       默认值
 var          用来存放现在指到的成员                          N      String               否           无

                                                                                               Arrays
                                                                                              Collection
                                                                                               Iterator             否           无
items         被迭代的集合对象                                    Y        Enumeration            
                                                                                               Map
                                                                                                String

varStatus     用来存放到指到的相关成员信息          N        String               否           无
begin           开始的位置                                             Y          int                    否           0
end              结束的位置                                             Y          int                   否           最后一个成员
setp             每次迭代的间隔数                                 Y          int                   否            1
-------------------------------------------------------------------------------------------------------------------------
Null 和 错误处理
.假若items为null时,则表示为一空的集合对象
.假若begin大于或等于items时,则迭代不运算
注意:
varName的范围只存在<c:forEach>的本体中,如果超出了本题,则不能取得varName的值。如:
<c:forEach items="${atts}" var="item">
</c:forEach>
${item}</br>
${item}则不会显示item的内容。<c:forEach>除了支持数组之外,还有标准的J2SE的结合类型,例如:
ArrayList,List,LinkedList,Vector,Stack和Set等等;另外包括java.util.Map类的对象,例如:
HashMap,Hashtable,Properties,Provider和Attributes。

另外<c:forEach>还提供了varStatus属性,主要用来存放现在指到成员的相关信息。例如:我们写成
varStatus="s",那么就会把信息存放到名称为s的属性当中。varStatus属性还提供另外四个属性:index,
count,fist和last,它们个自的意义如下:
------------------------------------------------------------------------------------------
   属性                    类型                                   意义
   index                   number                      现在指到成员的索引
   count                   number                      总共指到成员的总和
   first                     boolean                     现在指到成员是否为第一个
   last                     boolean                     现在指到成员是否为最后一个
-------------------------------------------------------------------------------------------
如下例子:
<%@page contentType="text/html;charset=gb2312"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%
 String atts[] = new String[5];
 atts[0]="hello";
 atts[1]="this";
 atts[2]="is";
 atts[3]="a";
 atts[4]="girl";
 request.setAttritue("atts",atts);
%>
<c:forEach items="${atts}" var="item" varStatus="s">
<h2><c:out value="${item}"/>的四种属性></h2>
 index: ${s.index}</br>
 count: ${s.count}</br>
 first: ${s.first}</br>
 last:  ${s.last}</br>
</c:forEach>

<c:forTokens>
<c:forTokens>:用来浏览一字符串中所有的成员,起成员是由定义符号(delimiters)所分隔的。
语法:
<c:forTokens items="stringFoTokens" delims="delimmmmiters" [var="varName"]
             [varStatus="varStatusName"] [begin="begin"] [end="end"] [step="step"]>
 ...body内容....
</c:forTokens>

Attribute
--------------------------------------------------------------------------------------------------------------------
 名称                                    说明                                               EL     类型      必须       默认值
 var                   用来存放现在指到的成员                                Y      String       否          无
 items                被迭代的字符串                                                Y      String       是          无
 delims              定义用来分割字符串的字符                            N      String       是          无
 varStatus          用来存放现在指到的相关成员信息                N      String       否          无
 begin               开始的位置                                                         Y       int           否           0
 end                 结束的位置                                                          Y       int          否           最后一个成员
 step                每次迭代间隔数                                                  Y       int           否           1
---------------------------------------------------------------------------------------------------------------------
限制:
.假若有begin属性时,begin必须大于等于0
.假若有end属性时,必须大于begin
.假若有step属性时,step必须大于等于1

Null 和 错误处理
.假如itmes为null时,则表示为有空的集合对象
.假若begin大于等于items的大小时,则迭代不运算

例子:
<c:forToken items="A,B,C,D,E,F,G" delims="," var="item>
${item}
</c:forToken>
items属性也可以用EL,例如:
<%
 String phonenumber="123-456-7899";
 request.setAttribute("userPhone",phonenumber);
%>
<c:forTokens items="${userPhone}" delims="-" var="item">
${item}
</c:forTokens>

URL操作
JSTL包含三个URL操作有关的标签,分别是: <c:import>,<c:redirect>和<c:url>。它们的主要功能是:
用来将其他文件的内容包含起来,网页的向导,还有url的产生。

posted @ 2006-07-04 13:47 多力宇扬 阅读(566) | 评论 (0)编辑 收藏

应聘Java笔试时可能出现问题
Java基础方面:
1、作用域public,private,protected,以及不写时的区别
Public、Protected、Private是成员访问修饰符;
final、abstract、transient、synchronized、native、strictfp是非访问成员修饰符。
可见性PublicProtectedDefaultPrivate
同一个类是是是是
同一个包中的类是是是否
同一个包中的子类是是是否
同一包外的子类是是否否
同一包外的非子类是否否否

Java的基本包
java.lang 其中包含有:
接口:Comparable、Cloneable、Runable等
类:八个基本数据类型封装类、Math、Runtime、Object、String、StringBuffer、Thread、Exception等

集合框架
集合是将多个元素组成一个单元的对象。集合用于存储、检索和操纵数据。
集合框架提供管理对象集合的接口和类。它包含几个组件,接口是表示集合的抽象数据类型,用于操纵集合;类是用于存储集合的实际数据对象;算法是用于操纵集合的。

2、ArrayList和Vector的区别,HashMap和Hashtable的区别
答:就ArrayList与Vector主要从二方面来说.
一.同步性:Vector是线程安全的,也就是说是同步的,而ArrayList是线程序不安全的,不是同步的
二.数据增长:当需要增长时,Vector默认增长为原来一培,而ArrayList却是原来的一半

ArrayList,Vector, LinkedList的存储性能和特性
ArrayList和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,Vector由于使用了synchronized方法(线程安全),通常性能上较ArrayList差,而LinkedList使用双向链表实现存储,按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快。

就HashMap与HashTable主要从三方面来说.
一.历史原因:Hashtable是基于陈旧的Dictionary类的,HashMap是Java 1.2引进的Map接口的一实现
二.同步性:Hashtable是线程安全的,也就是说是同步的,而HashMap是线程序不安全的,不是同步的
三.值:只有HashMap允许在一个集合中有一个null键和在一个集合中有多个null值

Hashtable是HashMap的同步版本;HashMap允许有null值和一个null键,但是,Hashtable不允许有任何内容为null

Hashtable类的对象必须覆盖Object类的hashCode()和equals()方法

关于其他集合类型:
一.ArrayList 提供快速遍历和快速访问。现在设计了新的 RandomAccess 接口,它指出这种列表支持快速随机访问。Vector也实现了RandomAccess 接口。
二.遍历HashSet与HashMap时,其顺序是未知的(但添加删除快)。LinkedHashSet和LinkedHashSet是按照元素的插入的顺序遍历的(遍历快)。
三.TreeSet和TreeMap将保证元素按照元素的自然顺序进行排列。也可以使用一个用户自己实现的比较规则。
四、HashSet有一个散列表支持它。它为基本操作提供固定时间性能。TreeSet它确保了排序集将按元素升序,根据自然顺序排序。

Dictionary类
主要用于将关键字转换成值,该类接收一个关键字并返回一个值。Dictionary是一个抽象类,它是H
Hashtable的超类。
Properties类
扩展了Hashtable类,但Properties对象的关键字和值必须是String类型,并能将对象写入一个输出流并保存在一个文件中,然后可以把它读回一个输入流。


如果需要维护和搜索一个部件列表,它们由唯一的字母数字序列号标示,其中的部件是Part类型,这时应该使用哪种集合?如果我们改变需求,你也需要能够按顺序、按它们的序列号打印出部件?
1、应该选择HashMap
2、应该选择TreeMap

3、char型变量中能不能存贮一个中文汉字?为什么?
答:是能够定义成为一个中文的,因为java中以unicode编码,一个char占16个字节,所以放一个中文是没问题的

4、多线程有几种实现方法,都是什么?同步有几种实现方法,都是什么?
答:多线程有两种实现方法,分别是继承Thread类与实现Runnable接口
同步的实现方面有两种,分别是synchronized,wait与notify

GC是什么? 为什么要有GC?
GC是垃圾收集的意思(Gabage Collection),内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java语言没有提供释放已分配内存的显示操作方法。

7、垃圾回收机制,如何优化程序?
当一个对象失去引用或者离开了作用域后,就成为垃圾而被Java运行环境自动清除,清除垃圾就是清除这些对象。
Java垃圾回收机制的特点是:
1、垃圾回收机制自动运行。系统提供一个低优先级的线程来跟踪内存的分配情况。如果发现某个内存单元不再使用,就清除它。
2、何时清除垃圾是不可预期的。
3、垃圾回收机制随JVM的不同而不同。

Java的垃圾搜索器为内存管理器提供一种自动解决方案。缺点是不能完全控制它什么时候执行以及什么时候不执行。
当垃圾搜集器运行时,其目的是查找和删除不能被访问的对象。
垃圾搜集器受JVM控制,JVM决定什么时候运行垃圾搜集器。从Java程序内可以请求JVM运行垃圾搜集器,但是,在任何情况下都无法保证JVM会答应你的请求。JVM通常会在它感到内存减少时运行垃圾搜集器。
垃圾收集器运行时,当它发现一个对象不能被任何活线程访问时,它将认为该对象符合删除条件,它可能在某时删除该对象。
垃圾收集器不能保证有足够的内存,它只能保证可以使用的内存将尽可能被有效的管理。
使对象符合垃圾搜集器搜索条件的情况有:出现空引用、重新为引用变量赋值、隔离引用。

强制执行垃圾搜集:
Runtime对象为直接与虚拟机通信提供一种机制。System类可以调用与其相同的方法。
请求垃圾收集器的最简单的方法是:System.gc();

Javac编译选项?
G产生调试信息
g:none不产生调试信息
verbose输出编译器消息,可以知道程序编译时用到了哪些Java类
Noware编译时不产生警告信息
encoding指出原文件的编码方式
D指定类文件产生的目录
classPath指出用户class文件的路径
sourcePath指出用户源文件路径

9、介绍JAVA中的Collection FrameWork(包括如何写自己的数据结构)?
答:Collection FrameWork如下:
核心接口有:
CollectionSetSorted Set
ListMapSorted Map

Set接口:不允许重复的元素。它对add、equals、hashCode方法增加了限制
SortedSet接口:扩展了Set接口,此接口的元素按升序排序。
List接口:一些集合具有顺序,即在一个项目后添加另一个项目。列表可以有重复元素。提供了ListIterator,允许向前或向后移动元素。
Map接口:将键映射到值得对象。Map不能包含重复键,但可以包含重复值。每个键最多都只能映射到一个值。

核心设计类:
Map 设计Set 设计List 设计
HashMapHashSetArrayList
HashtableLinkedHashSetVector
TreeMapTreeSetLinkedLisk
LinkedHasMap

散列表是最快的数据存储结构,它是一个数组。数据存储在数组中散列函数指定的特定下标。散列函数是一组输入数据和一组整数之间的映射。

集合类和接口层次

Collections是一个类,带有用于处理集合的静态实用方法
Collection是一个接口,带有多数集合常用的方法声明,包括add、remove、contains、size、iterator

Collection是最基本的集合接口,一个Collection代表一组Object,即Collection的元素(Elements)
Map提供key到value的映射

集合框架的优点:
提供一组可用的集合接口,可以方便地扩展或改写集合;
接口和算法的可重用性提高了软件的可重用性;
提供了有效的数据结构和算法,减少了编程工作。

10、Java中异常处理机制,事件机制?
事件代表了组件之间的交互。是一种在源对象和监听对象之间,某种状态发生变化的传递机制。
通过事件处理机制,可以让一些组件作为事件源,发出可被组件环境或其它组件接收的事件。这样,不同的组件就可以组合在一起,组件之间通过事件传递进行通信,构成一个应用。
在java中实现事件机制的事件模型由三个部分构成:一个事件对象用于描述事件源的状态变化;一个事件源将会产生事件,提供注册的事件监听器的方法,把事件发送到监听器;事件监听器接收事件通知,实现该事件的监听器接口。

异常实际上是程序中错误导致中断了正常的指令流的一种事件.
Java异常处理用于在方法中能检查出错误但不能处理错误的情况,在这样的方法中将抛出一个异常。如果一个异常与某个catch程序块中的参数匹配,那么就执行该catch块中的代码。指出try catch finally的工作顺序。

运行时异常与一般异常有何异同?
异常表示程序运行过程中可能出现的非正常状态,运行时异常表示虚拟机的通常操作中可能遇到的异常,是一种常见运行错误。java编译器要求方法必须声明抛出可能发生的非运行时异常,但是并不要求必须声明抛出未被捕获的运行时异常。

事件有哪些?

什么是断言机制?
断言从JDK1.4版开始引入,它让开发期间测试假设,而没有付出为异常编写异常处理程序方面的代价,一旦程序完成开发,并全部部署,假设将从不会发生。
主要作用:因为在开发时对自己的假设非常肯定,所以不想花费时间来编写异常处理代码。断言让在开发期间测试你的假设。
private void method(int num){
assert(num>=0);//这里假定参数num是正数,如果不是真的将抛出一个AssertionError错误
useNum(num+x);
}
断言有两种形式:简单和非常简单。
非常简单:
private void doStuff(){
assert(y>x);
//其他代码
}
简单:
将通过表达式的值向错误跟踪栈中添加更多信息,提供了更多调式帮助信息。
private void doStuff(){
assert(y>x):”y is ”+y+” x is”+x;
//其他代码
}
运行时启用断言:
java –ea com.geeksanonymous.TestClass

运行时禁用断言:
java –da com.geeksanonymous.TestClass

11、JAVA中的多形与继承?
希望大家补上,谢谢

对象是定义了边界的、与要解决的问题有关的概念或事物。它们用于帮助理解现实世界。
类是拥有相同特性、共同的行为和共同的关系的一组对象。
封装是让开发者有选择地隐藏类中的特性和方法的过程
继承是允许通过重用现有类来构建新类的特性。]
多态性使用同一函数在不同的类上具有不同的行为。Java中的多态性是通过方法的动态绑定实现的。

12、抽象类与接口?
答:抽象类与接口都用于抽象,但是抽象类(JAVA中)可以有自己的部分实现,而接口则完全是一个标识(同时有多重继承的功能)。

abstract的method是否可同时是static,是否可同时是native,是否可同时是synchronized? 都不能

接口是否可继承接口? 抽象类是否可实现(implements)接口? 抽象类是否可继承实体类(concrete class)?
接口可以继承接口。抽象类可以实现(implements)接口,抽象类可继承实体类,但前提是实体类必须有明确的构造函数。

Anonymous Inner Class (匿名内部类) 是否可以extends(继承)其它类,是否可以implements(实现)interface(接口)?
可以继承其他类或完成其他接口,在swing编程中常用此方式。

IO流
字节流:数据在存储时与传输时都是以字节为单位进行的。通常用于读写二进制数据,如图像和声音文件。
字符流:数据在存储与传输时都是以字符为单位进行的。

流:对数据源的一种抽象,其目的是想用统一的方式访问各种不同的数据源(文件、网络、内存的缓冲区)

文件读写的基本类:File类提供定位本地文件系统,描述文件和目录的功能。

管道流用于在线程之间通信:PipedInputStream、PipedOutputStream、PipedReader、PipedWriter
线程1àPipedOutputStreamàPipedInputStreamà线程2

键盘输入:
try{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
String s=br.readLine();
System.out.println(s);
}catch(Exception e){
}

文件输入输出:
try{
File f=new File("test.txt");
FileOutputStream fout=new FileOutputStream(f);
fout.write(System.in.read());
fout.close();
FileInputStream fin=new FileInputStream(f);
int size=fin.available();
for(int i=0;i<size;i++){
System.out.print((char)fin.read());
}
fin.close();
}catch(Exception e){
}

通过网络传输文件:
客户端:
File f=new File("bk.exe");
FileInputStream fin=new FileInputStream(f);
Socket st=new Socket("localhost",6000);
BufferedOutputStream bout=new BufferedOutputStream(st.getOutputStream());
int size=fin.available();
for(int i=0;i<size;i++){
bout.write(fin.read());
}
服务器端:
ServerSocket server=new ServerSocket(6000);
Socket st=server.accept();
File f=new File("kk.exe");
BufferedInputStream bin=new BufferedInputStream(st.getInputStream());
FileOutputStream fout=new FileOutputStream(f);
int i=0;
while(i!=-1){
i=bin.read();
fout.write(i);
}

串行化的注意事项以及如何实现串行化
对象的寿命通常随着生成该对象的程序的终止而终止。有时候,可能需要将对象的状态保存下来,在需要时再将对象恢复。我们把对象的这种能记录自己的状态以便将来再生的能力,叫做对象的持续性(persistence)。对象通过写出描述自己状态的数值来记录自己,这个过程叫对象的串行化(Serialization)。
序列化的过程就是对象写入字节流和从字节流中读取对象。将对象状态转换成字节流之后,可以用java.io包中的各种字节流类将其保存到文件中,管道到另一线程中或通过网络连接将对象数据发送到另一主机。
一:对象序列化可以实现分布式对象。
二:java对象序列化不仅保留一个对象的数据,而且递归保存对象引用的每个对象的数据。
// 序列化 today's date 到一个文件中.
   FileOutputStream f = new FileOutputStream("tmp");
   ObjectOutputStream s = new ObjectOutputStream(f);
   s.writeObject("Today");
   s.writeObject(new Date());
   s.flush();
//从文件中反序列化 string 对象和 date 对象
   FileInputStream in = new FileInputStream("tmp");
   ObjectInputStream s = new ObjectInputStream(in);
   String today = (String)s.readObject();
   Date date = (Date)s.readObject();
记住,对象流不序列化static或transient。
序列化通常可以自动完成,但有时可能要对这个过程进行控制。java可以将类声明为serializable,但仍可手工控制声明为static或transient的数据成员。
如果一个类要完全负责自己的序列化,则实现Externalizable接口而不是Serializable接口。Externalizable接口定义包括两个方法writeExternal()与readExternal()。利用这些方法可以控制对象数据成员如何写入字节流

NIO的特征
l旧的I/O是以字节为单位进行读写的,而新的I/O是以块为单位进行读写的
l以新的Channel抽象类来配合节点类
l使用Buffer的概念来进行基本数据类型的存取
l增加更多字节编码的支持
l内存映像及数据锁定的支持
l提供非阻塞的存取机制
l提供正则表达式式的验证机制


import java.io.*;
import java.nio.*;
import java.nio.channels.*;
import java.nio.channels.spi.*;
import java.net.*;
import java.util.*;

class NBTest {
NBTest(){}
public void startServer() throws Exception{
int channels = 0;
int nKeys = 0;
int currentSelector = 0;
Selector selector = Selector.open();

//建立Channel 并绑定到9000端口
ServerSocketChannel ssc = ServerSocketChannel.open();
InetSocketAddress address = new InetSocketAddress(InetAddress.getLocalHost(),9000);
ssc.socket().bind(address);

//使设定non-blocking的方式。
ssc.configureBlocking(false);

//向Selector注册Channel及我们有兴趣的事件
SelectionKey s = ssc.register(selector, SelectionKey.OP_ACCEPT);
printKeyInfo(s);

while(true) //不断的轮询
{
debug("NBTest: Starting select");
//Selector通过select方法通知我们我们感兴趣的事件发生了。
nKeys = selector.select();
//如果有我们注册的事情发生了,它的传回值就会大于0
if(nKeys > 0){
debug("NBTest: Number of keys after select operation: " +nKeys);
//Selector传回一组SelectionKeys
//我们从这些key中的channel()方法中取得我们刚刚注册的channel。
Set selectedKeys = selector.selectedKeys();
Iterator i = selectedKeys.iterator();
while(i.hasNext()){
s = (SelectionKey) i.next();
printKeyInfo(s);
debug("NBTest: Nr Keys in selector: " +selector.keys().size());

//一个key被处理完成后,就都被从就绪关键字(ready keys)列表中除去
i.remove();
if(s.isAcceptable()){
// 从channel()中取得我们刚刚注册的channel。
Socket socket = ((ServerSocketChannel)s.channel()).accept().socket();
SocketChannel sc = socket.getChannel();
sc.configureBlocking(false);
sc.register(selector, SelectionKey.OP_READ |SelectionKey.OP_WRITE);
System.out.println(++channels);
}else{
debug("NBTest: Channel not acceptable");
}
}
}else{
debug("NBTest: Select finished without any keys.");
}
}
}

private static void debug(String s){
System.out.println(s);
}

private static void printKeyInfo(SelectionKey sk)
{
String s = new String();
s = "Att: " + (sk.attachment() == null ? "no" : "yes");
s += ", Read: " + sk.isReadable();
s += ", Acpt: " + sk.isAcceptable();
s += ", Cnct: " + sk.isConnectable();
s += ", Wrt: " + sk.isWritable();
s += ", Valid: " + sk.isValid();
s += ", Ops: " + sk.interestOps();
debug(s);
}

public static void main (String args[])
{
NBTest nbTest = new NBTest();
try{
nbTest.startServer();
}catch(Exception e){
e.printStackTrace();
}
}
}

Socket通信(TCP、UDP区别及Java实现方式)
套接字是一种进程间的数据交换机制。客户端和服务器通过套接字建立连接和进行通信。套接字是由IP地址、传输协议和一个端口号三部分组成的。
TCP/IP协议:其中TCP 为传输控制协议是传输层协议,
功能TCPUDP
数据传输连续的有序数据流消息传输
多路功能接收主机根据端口号决定数据流向那个应用相同
可靠传输使用TCP头部的序列与确认字段进行数据确认无
流量控制使用窗口机制的流量控制无
连接使用3次握手建立连接;连接后一直保持连接直到终止连接无连接

URL的组件:协议、IP地址或主机名、端口号和实际文件路径

import java.net.*;
import java.io.*;

public class DatagramServer{
public static DatagramSocket ds;
public static int clientport=1089,serverport=1090;
public static void main(String args[]) throws Exception{
byte buffer[]=new byte[1024];
ds=new DatagramSocket(serverport);
BufferedReader dis=new BufferedReader(new InputStreamReader(System.in));
System.out.println("服务器正等待输入");
InetAddress ia=InetAddress.getByName("localhost");
while(true){
String str=dis.readLine();
if(str==null||str.equals("end")){
break;
}
buffer=str.getBytes();
ds.send(new DatagramPacket(buffer,str.length(),ia,clientport));
}
}
}

import java.net.*;
import java.io.*;

public class DatagramClient{
public static DatagramSocket ds;
public static byte buffer[]=new byte[1024];
public static int clientport=1089,serverport=1090;
public static void main(String args[]) throws Exception{
ds=new DatagramSocket(clientport);
System.out.println("客户端正在等待服务器发送数据");
while(true){
DatagramPacket p=new DatagramPacket(buffer,buffer.length);
ds.receive(p);
String psx=new String(p.getData(),0,p.getLength());
System.out.println(psx);
}
}
}

13、Java 的通信编程,编程题(或问答),用JAVA SOCKET编程,读服务器几个字符,再写入本地显示?
答:Server端程序:
package test;
import java.net.*;
import java.io.*;

public class Server {
private ServerSocket ss;
private Socket socket;
private BufferedReader in;
private PrintWriter out;
public Server() {
try {
ss=new ServerSocket(10000);
while(true) {
socket = ss.accept();
String RemoteIP = socket.getInetAddress().getHostAddress();
String RemotePort = ":"+socket.getLocalPort();
System.out.println("A client come in!IP:"+RemoteIP+RemotePort);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line = in.readLine();
System.out.println("Cleint send is :" + line);
out = new PrintWriter(socket.getOutputStream(),true);
out.println("Your Message Received!");
out.close();
in.close();
socket.close();
}
}catch (IOException e) {
out.println("wrong");
}
}
public static void main(String[] args) {
new Server();
}
};

Client端程序:
package test;
import java.io.*;
import java.net.*;

public class Client {
Socket socket;
BufferedReader in;
PrintWriter out;
public Client() {
try {
System.out.println("Try to Connect to 127.0.0.1:10000");
socket = new Socket("127.0.0.1",10000);
System.out.println("The Server Connected!");
System.out.println("Please enter some Character:");
BufferedReader line = new BufferedReader(new

InputStreamReader(System.in));
out = new PrintWriter(socket.getOutputStream(),true);
out.println(line.readLine());
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
System.out.println(in.readLine());
out.close();
in.close();
socket.close();
}catch(IOException e) {
out.println("Wrong");
}
}
public static void main(String[] args) {
new Client();
}
};

常见排序法:
public class Sort{
public static int count=0;
public boolean LT(int num1,int num2){
return num1<num2;
}
public void output(int[] array){
System.out.print("第"+count+"次排序:");
for(int i=0;i<array.length;i++)
System.out.print(array[i]+"    ");
System.out.println();
}

//冒泡排序法
public void BubbleSort(int[] array){
boolean swap=true;
int index=0;

int i=0;
while(i<array.length-1){
int temp=array[i];
for(int j=i;j<array.length;j++){
if(!LT(array[i],array[j])){
int temp2=array[i];
array[i]=array[j];
array[j]=temp2;
swap=true;
index=j;
}else{
swap=false;
}
}
i++;
if(swap){
array[i]=array[index];
array[index]=temp;
i++;
}
output(array);
}
}

//直接插入排序法
public void InsertSort(int[] array){
for(int i=1;i<array.length;++i){
if (LT(array[i],array[i-1])){
int temp=array[i];
array[i]=array[i-1];
array[i-1]=temp;
for(int j=i-1;j>0;--j){
if(LT(array[j],array[j-1])){
array[j]=array[j-1];
array[j-1]=temp;
}else{
break;
}
}
output(array);
}
}
}

//快速排序法
private int Partition(int array[],int low,int high){
int temp=array[low];
int pivotkey=array[low];
while(low<high){
while(low<high&&array[high]>pivotkey)--high;
array[low]=array[high];
while(low<high&&array[low]<=pivotkey)++low;
array[high]=array[low];
}
array[low]=temp;
output(array);
return low;
}

public void QSort(int array[],int low,int high){
if(low<high){
int pivotloc=Partition(array,low,high);
QSort(array,low,pivotloc-1);
QSort(array,pivotloc+1,high);
}
}

void QuickSort(int array[]){
QSort(array,0,array.length-1);
}
public static void main(String args[]){
int array[]={49,38,65,97,76,13,27,49};
Sort sort=new Sort();

System.out.println("===================================");
sort.output(array);
System.out.println("优化冒泡排序法");
sort.BubbleSort(array);

System.out.println();
System.out.println("===================================");
array=new int[]{49,38,65,97,76,13,27,49};
sort.output(array);
System.out.println("直接插入排序法");
sort.InsertSort(array);

System.out.println();
System.out.println("===================================");
array=new int[]{49,38,65,97,76,13,27,49};
sort.output(array);
System.out.println("快速排序法");
sort.QuickSort(array);
}
}

14、如在COLLECTION框架中,实现比较要实现什么样的接口?
Collection框架中实现比较要实现Comparable 接口和 Comparator 接口

什么是线程?
线程与进程相似,是一段完成某个特定功能的代码,是程序中单个顺序的流控制;但与进程不同的是,同类的多个线程是共享一块内存空间和一组系统资源,而线程本身的数据通常只有微处理器的寄存器数据,以及一个供程序执行时使用的堆栈。所以系统在产生一个线程,或者在各个线程之间切换时,负担要比进程小的多,正因如此,线程被称为轻负荷进程(light-weight process)。一个进程中可以包含多个线程。

  一个线程是一个程序内部的顺序控制流。
  1. 进程:每个进程都有独立的代码和数据空间(进程上下文) ,进程切换的开销大。
  2. 线程:轻量的进程,同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换的开销小。
  3. 多进程:在操作系统中,能同时运行多个任务程序。
4. 多线程:在同一应用程序中,有多个顺序流同时执行。

同步和异步有和异同,在什么情况下分别使用他们?
临界资源问题
线程都是独立的,而且异步执行,也就是说每个线程都包含了运行时所需要的数据或方法,而不需要外部的资源或方法,也不必关心其它线程的状态或行为。但是经常有一些同时运行的线程需要共享数据,此时就需考虑其他线程的状态和行为,否则就不能保证程序的运行结果的正确性。
我们需要做的是允许一个线程彻底完成其任务后,再允许下一个线程执行。必须保证一个共享的资源一次只能被一个线程使用。实现此目的的过程称为同步。
同步是用于确保资源一次只能被一个线程使用的过程。
同步对于单线程程序没有任何好处。使用同步比非同步的性能差三到四倍。

线程方法介绍:
构造函数:
Thread()
Thread(Runable target)
Thread(Runable target,String name)
Thread(ThreadGroup group,Runable target)
Thread(ThreadGroup group,Runable target,String name)
Thread(ThreadGroup group,String name)

用于完成一个线程“实际功能”的代码放在run方法中。Run方法可以在Thread的子类中重写,也可以在Runable对象中重写。

一旦线程死去,它就永远不能再重新启动,否则会抛出异常。用start方法启动一个已经启动的线程也会抛出异常。

isAlive、interrupt、Thread.currentThread、suspend、resume、stop

Sleep方法可以使低优先级的线程得到执行的机会,Yield方法只能使同优先级的线程有执行的机会。Join方法能够使调用该方法的线程在此之前执行完毕,在该方法之后,调用join方法的线程不会产生输出了,


Wait与notify使用时,需要注意的事项?
它们只能用于synchronized同步块中;
它们需要配对使用;
Wait一般出现在一个while循环中,while语句使用一个boolean标志控制。

死锁
当被锁定的A对象试图访问另一个被锁定的B对象,B对象同时又要访问已被锁定的A对象。这样导致两个线程都在等待另一个线程释放资源,这样就出现了死锁。

16、JAVA多线程编程。 用JAVA写一个多线程程序,如写四个线程,二个加1,二个对一个变量减一,输出。
希望大家补上,谢谢

17、STRING与STRINGBUFFER的区别。
答:STRING的长度是不可变的,STRINGBUFFER的长度是可变的。如果你对字符串中的内容经常进行操作,特别是内容要修改时,那么使用StringBuffer,如果最后需要String,那么使用StringBuffer的toString()方法

String s = new String("xyz");创建了几个String Object? 两个

JDBC调用数据库的基本步骤

Weblogic Server中的JDBC配置
1、建立到指定数据库的连接池Connection Pool
2、建立基于该连接池的数据源DataSource
3、访问数据库时通过数据源的JNDI名字查找到该数据源,然后通过数据源获得数据库连接对象。得到该对象后就可以依次生成数据库语句对象和结果集对象,进行相应的数据库操作。

import java.sql.*;
import javax.naming.*;
import javax.sql.*;
import java.util.*;
import javax.rmi.*;

public class DataSourceTest{
private static Context getInitialContext() throws Exception{
String url="t3://localhost:7001";
String user="system";
String password="11111111";
Properties properties=null;

try{
properties=new Properties();
properties.put(Context.INITIAL_CONTEXT_FACTORY,
"weblogic.jndi.WLInitialContextFactory");
properties.put(Context.PROVIDER_URL,url);

if(user!=null){
properties.put(Context.SECURITY_PRINCIPAL,user);
properties.put(Context.SECURITY_CREDENTIALS,
password==null?"":password);
}

return new InitialContext(properties);
}catch(Exception e){
throw e;
}
}

public static void main(String args[]){
UserTransaction tx=null;
DataSource ds=null;
Context ctx=null;
Connection myConn=null;

try{
ctx=getInitialContext();

tx=(UserTranscation)ctx.lookup("javax.transcation.UserTranscation");
tx.begin();

ds=(DataSource)ctx.lookup("myTxDataSource");
}catch(Exception e){
e.printStackTrace();
}

Statement myStatement=null;
ResultSet myResultSet=null;

try{
myConn=ds.getConnection();
myStatement=myConn.createStatement();
myResultSet=myStatement.executeQuery(
"select fullname from employee");

while(myResultSet.next()){
System.out.println(myResultSet.getString("fullname"));
}

tx.commit();
}catch(Exception e){
try{
tx.rollback();
}catch(Exception e){
}
}finally{
myStatement.close();
myConn.close();
}
}
}

JavaMail发邮件的步骤:
Properties props=System.getProperties();
props.put(“mail.smtp.host”,”*******”); //设置相关的属性
try{
    //创建一个会话对象
    Session session=Session.getDefaultInstance(props,null);
    //创建一个消息对象
    MimeMessage message=new MimeMessage(session);
    message.setText(“*****”); //发送文本格式的邮件
    message.setSubject(“*****”);
    message.setFrom(“*****”);
    message.addRecipient(Message.RecipientType.To,
                        new InternetAddress(“******”));
   //使用传送类的send方法发送消息
   Transport.send(message);
}catch(MessagingException me){
          me.printStackTrace();}

解析XML文件的几种方式和区别
XML解析器使用的两种基本API是:
文档对象模型DOM,一种基于树结构的API。它定义了一组java接口,用于创建、访问和操纵XML文档的内部结构。它是基于对象。整个XML文档被作为对象体系结构排列进行解析和存储,应用程序可以随机访问这些对象。
DOM主要用于:在结构上修改XML文档时;在内存中与其他应用程序共享文档时。

SAX提供一种用于解析XML文档的事件驱动模型,使用SAX接口的XML处理器并不创建数据结构,而是扫描输入的XML文档,并生成元素开始、元素结束等事件,在发生事件时,解析器会通知应用程序。
SAX优点:在解析大型文档时,不必将整个文件加载到内存中,因此占有的内存比DOM少。在只需要一个信息子集时,SAX忽略不需要的数据,而DOM无法做到这点。
SAX的缺点是:必须按到达顺序处理数据,不能对文档进行随即访问。SAX是只读的,它是设计来读取XML文档而不是写入的。文档只能遍历一次。

使用DOM API查找XML文档中的元素和属性
import org.w3c.dom.*;
import javax.xml.parsers.*;
import java.io.*;
import java.net.URL;

public class BookDetails{
public BookDetails(String filename){
Document doc=null;
try{
DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
DocumentBuilder db=dbf.newDocumentBuilder();
doc=db.parse(new File(filename));

String nm="http://www.123books.com/booktitles";
String local="a";
String ob="http://www.onlinebooks.com";

System.out.println(nm+"名字空间中的元素");
NodeList nl=doc.getElementsByTagNameNS(nm,"*");
for(int i=0;i<nl.getLength();i++){
Node n=nl.item(i);
System.out.println(n.getNodeName());
}

System.out.println("\n 名称为 "+local+" 的元素");
nl=doc.getElementsByTagNameNS("*",local);
for(int i=0;i<nl.getLength();i++){
Node n=nl.item(i);
System.out.println(n.getNodeName());
}

System.out.println("\n名字空间 "+ob+" 中的属性");
nl=doc.getElementsByTagName("*");
for(int i=0;i<nl.getLength();i++){
if(nl.item(i) instanceof Element){
Text t=(Text)nl.item(i).getFirstChild();
Element e=(Element)nl.item(i);
Attr a=e.getAttributeNodeNS(ob,"class");
if(a!=null){
String val=a.getNodeValue();
System.out.println("<"+val+">"+t.getNodeValue()+"</"+val+">");
}
}
}
}catch(Exception e){
e.printStackTrace();
}
}

public static void main(String args[]){
BookDetails nsd=null;
if(args.length>=1){
nsd=new BookDetails(args[0]);
}else{
System.out.println("Books.xml");
}
}
}
使用SAX API解析XML文档
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

public class SAXParserHandler extends DefaultHanlder{
public void startDocument() throws SAXException{
System.out.println("起始文档");
}

public void endDocument() throws SAXException{
System.out.println("结束文档");
}

//在遇到字符数据时激发
public void characters(char[] ch,int start,int lenght) throws SAXException){
String charString=new String(ch,start,lenght);
System.out.println("字符:"+charString);
}

public void startElement(String namespaceURI,String localName,String qName,
Attributes atts)throws SAXException{
System.out.println("起始元素"+qName);
for(int i=0;i<atts.getLength();i++){
System.out.println("属性值:"+atts.getvalue(i));
}
}

public void endElement(String namespaceURI,String localName,String qName)
throws SAXException{
System.out.println("结束元素"+qName);
}

public static void main(String args[]) throws Exception{
SAXParserFactory factory=SAXParserFactory.newInstance();
SAXParser parser=factory.newSAXParser();
parser.parse("book.xml",new SAXParserHanlder());
}
}
使用DOM API写XML文档
import org.w3c.dom.*;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*;

import java.io.*;

public class Student{
public static void main(String args[]){
Document doc;
Element students;
Element stud;
Element fName;
Element sName;
try{
DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance();
DocumentBuilder db=dbf.newDocumentBuilder();
doc=db.newDocument();

stud=doc.createElement("Student");

fName=doc.createElement("FirstName");;
fName.appendChild(doc.createTextNode("John"));
stud.appendChild(fName);

sName=doc.createElement("Surname");
sName.appendChild(doc.createTextNode("David"));
stud.appendChild(sName);

students=doc.createElement("Students");
students.setAttribute("Department","Mathematics");
students.appendChild(stud);

doc.appendChild(students);

TransformerFactory tf=TransformerFactory.newInstance();
Transformer transformer=tf.newTransformer();
transformer.transform(new DOMSource(doc),new StreamResult(System.out));

}catch(Exception e){
e.printStackTrace();
}
}
}
使用DOM API显示现有XML文档内容

使用DOM API将XML文档数据插入数据库

使用DOM API根据数据库创建XML文档

Java的国际化
国际化是为了将应用程序发布在多个地区(locale)而进行准备的过程。不同地区标识了各个特定的国家在信息表现上所广泛使用的语言、流通货币、字符集、日期格式及其他要素。

支持国际化的应用程序具有以下特点:
1、不用改变代码就可以支持另外的语言。
2、文本元素、消息和图片保存在源代码之外。
3、将于文化背景有关的数据,比如日期和时间、十进制数值以及流通货币,根据用户所用的语言和所在地理位置进行正确格式化。
4、支持非标准字符集。
5、应用程序可以快速适应新的语言区域。

为了使一个应用程序国际化,:
1、必须将用户所见到的硬编码字符(如标签、工具提示和错误信息等)替换成包含在资源包ResourceBundle中的字符。它是一个java属性文件,它将关键字映射为字符值。并且可以使用多个不同语言版本的ResourceBundle,这样将可以对于不同语言提供不同的字符串。
2、使用Locale对象,可以使数据格式化为与地区相关的数据。
3、国际化的应用程序还必须使用统一的字符编码标准字符集。

应用服务器有那些?

Servlet方面
什么是Servlet?
Servlet是J2EE应用框架中部署于Web层的Web组件,运行在支持Servlet的Web服务器或应用服务器上。Servlet为客户端和服务器端的信息处理提供了一种“请求/响应”机制。
客户程序将请求发送到服务器;服务器将请求发送到Servlet;依据客户程序的请求,Servlet动态地构造回答信息并返回给服务器;服务器将回答返回给客户程序。

什么是JSP?
JSP是J2EE应用框架中部署于Web层的Web组件,是对Servlet技术的扩展。它使在静态的页面中加入动态的内容变得非常容易。并且通过使用标签库可以大大节省开发时间;将JavaBean与JSP一起使用可以将数据表示和程序实现分离。

在MVC架构模式中:
使用Servlet作为控制器,而JSP作为数据视图。

CGI与Servlet的区别?
CGI(公共网关接口)是一项标准,使WEB服务器可以与外部应用程序交互。但是该技术存在一些严重的限制:
1、CGI应用程序占用资源很多。当系统要处理来自一个用户的请求时,就会创建一个新的进程来处理该请求,一旦CGI脚本停止执行,系统就必须收回该进程。这种重量级进程的经常启动和停止非常低效。
2、CGI很难链接于请求进程的其他阶段,因为在WEB服务器上它们运行于不同的进程。这就很难处理授权、工作流和日志记录工作。

Java Servlet技术提供了一个基于组件、与平台无关的方法来构建WEB应用程序。Servlet没有标准CGI应用程序所遇到的性能局限。
Servlet比CGI更高效是因为:
Servlet应用中将只创建一个单一个重量级进程,并对每个用户请求使用更轻量级的线程来完成请求处理,并且这些线程是由JVM自动维护。每个客户端请求对应一个线程,每个Servlet类在Servlet容器中只存在一个唯一的对象(实例)。Servlet类首次加载后将常驻内存。

1、说一说Servlet的生命周期?
答:在第一次请求Servlet时将创建Servlet实例,容器调用实例的init方法,如果容器有请求要传送给servlet,它就会调用servlet实例的Service方法。一个请求将作为一个线程。如果服务器要销毁servlet实例就会调用servlet实例的destory方法,否则该实例将会常驻内存。

2、Servlet版本间(忘了问的是哪两个版本了)的不同?
希望大家补上,谢谢

会话根中技术
用户认证:使用用户名和口令进行验证来让客户端访问某些资源。
隐藏表单字段:用于保存一个浏览器在服务器中的相关信息。
URL重写:在URL后面添加附加信息
持久Cookie:在请求和响应头信息中添加和编辑信息

什么是会话对象?
会话对象用于在用户访问一个Web站点的多个页面时共享信息。任何时候用户第一次访问某个网页,系统都将创建一个会话。如果以后用户访问此网页,JSP将检索有关此会话的信息。只要服务器收到此用户的请求,则会话就会持续,如果经过一段时间没有收到此用户的新请求,会话就会终止。

3、JAVA SERVLET API中forward() 与redirect()的区别?
使用重定向:当调用sendRedirect方法时,Web容器就会向浏览器返回响应,指示需要新的URL。因为浏览器发出了完全崭新的请求,所以在重定向之前存储为请求属性的任何对象都会消失。
使用转发:当为一个请求调用转发时,请求就发送给服务器上另一个资源,而无需通知客户机由不同的资源处理请求。这个过程完全在Web容器内部进行,客户机绝不知晓。与重定向不同,转发过程中,对象可以存储在请求中,并发送给下一个资源使用。
因为转发过程完全在服务器上进行,与客户机没用通信,因此转发的性能优于重定向。
但是如果在JSP页面上使用图形的相对路径和其他资源,转发机制就会带来问题。因为浏览器无从得知发生了转发,所以相对路径只是相对初始的Servlet,而不是所转发到的JSP页面。使用JSP自定义标签可以解决这个问题。

如何现实servlet的单线程模式

servlet的配置

4、Servlet的基本架构
public class ServletName extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response) throws
ServletException, IOException {
}
public void doGet(HttpServletRequest request, HttpServletResponse response) throws
ServletException, IOException {
}
}

 

Jsp方面
1、jsp有哪些内置对象?作用分别是什么?
JSP的隐式对象
RequestJavax.servlet.ServletRequest它包含了有关浏览器请求的信息.通过该对象可以获得请求中的头信息、Cookie和请求参数。
Enumeration getHeaderNames()String getHeader(name)Cookie[] getCookies()Enumeration GetParameterNames()String getParameter(name)String[] GetParametervalues(name)HttpSession getSession(flag)
responseJavax.servlet.ServletResponse作为JSP页面处理结果返回给用户的响应存储在该对象中。并提供了设置响应内容、响应头以及重定向的方法(如cookies,头信息等)
Void setContentType(type)String getCharacterEncoding()Void addCookie(cookie)Void sendRedirect(url)
outJavax.servlet.jsp.JspWriter用于将内容写入JSP页面实例的输出流中,提供了几个方法使你能用于向浏览器回送输出结果。
pageContextJavax.servlet.jsp.PageContext描述了当前JSP页面的运行环境。可以返回JSP页面的其他隐式对象及其属性的访问,另外,它还实现将控制权从当前页面传输至其他页面的方法。
Void forward(path)PAGE_SCOPEREQUEST_SCOPESESSION_SCOPEAPPLICATION_SCOPEVoid setAtrribute(key,value,scope)Enumeration getAttributeNamesInScope(scope)Object getAttribute(key,scope)Void RemoveAttribute(key,scope)Object findAttribute(name)Int getAttributeScope(name)
sessionjavax.servlet.http.HttpSession会话对象存储有关此会话的信息,也可以将属性赋给一个会话,每个属性都有名称和值。会话对象主要用于存储和检索属性值。
Void setAttribute(name,data)Object getAttribute(name)
applicationjavax.servle.ServletContext存储了运行JSP页面的servlet以及在同一应用程序中的任何Web组件的上下文信息。
pageJava.lang.Object表示当前JSP页面的servlet实例
configjavax.servlet.ServletConfig该对象用于存取servlet实例的初始化参数。
Enumeration getInitParameterNames()String getInitParameter(name)
ExceptionJavax.lang.Throwable在某个页面抛出异常时,将转发至JSP错误页面,提供此对象是为了在JSP中处理错误。
String getMessage()Void printStackTrace(out)<%@ page errorPage=”error.jsp”%><%@ page isErrorPage=”true” %>


2、jsp有哪些动作?作用分别是什么?
答:JSP共有以下6种基本动作
ljsp:include:在页面被请求的时候引入一个文件。
ljsp:useBean:寻找或者实例化一个JavaBean。
ljsp:setProperty:设置JavaBean的属性。
ljsp:getProperty:输出某个JavaBean的属性。
ljsp:forward:把请求转到一个新的页面。
ljsp:plugin:根据浏览器类型为Java插件生成OBJECT或EMBED标记

3、JSP中动态INCLUDE与静态INCLUDE的区别?
答:动态INCLUDE用jsp:include动作实现
<jsp:include page="included.jsp" flush="true" />它总是会检查所含文件中的变化,适合用于包含动态页面,并且可以带参数
静态INCLUDE用include伪码实现,定不会检查所含文件的变化,适用于包含静态页面
<%@ include file="included.htm" %>

4、两种跳转方式分别是什么?有什么区别?
答:有两种,分别为:
<jsp:include page="included.jsp" flush="true">
<jsp:forward page= "nextpage.jsp"/>
前者页面不会转向include所指的页面,只是显示该页的结果,主页面还是原来的页面。执行完后还会回来,相当于函数调用。并且可以带参数.后者完全转向新页面,不会再回来。相当于go to 语句。

JSP的常用指令
<%@ include file=”localURL” %>
<%@ page attribute=”value1” %>
属性值缺省值示例
contentTypeMIME类型和字符集“text/hmt”contentType=“text/html;charset=ISO-8859-1“contentType=“text/xml“
Extends类名无Extends=“com.taglib.wdjsp.MyJspPage“
Import 类名或包名无
Session布尔值TrueSession=“true”
isThreadSafe布尔值True
ErrorPage
isErrorPage


<%@ taglib uri=”tagLibraryURL” prefix=”tagPrefix” %>

Jdbc
说出数据连接池的工作机制是什么?


1、可能会让你写一段Jdbc连Oracle的程序,并实现数据查询.
答:程序如下:
package hello.ant;
import java.sql.*;
public class jdbc {
String dbUrl="jdbc:oracle:thin:@127.0.0.1:1521:orcl";
String theUser="admin";
String thePw="manager";
Connection c=null;
Statement conn;
ResultSet rs=null;
public jdbc() {
try{
Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();
c = DriverManager.getConnection(dbUrl,theUser,thePw);
conn=c.createStatement();
}catch(Exception e){
e.printStackTrace();
}
}
public boolean executeUpdate(String sql) {
try {
conn.executeUpdate(sql);
return true;
} catch (SQLException e) {
e.printStackTrace();
return false;
}
}
public ResultSet executeQuery(String sql) {
rs=null;
try {
rs=conn.executeQuery(sql);
} catch (SQLException e) {
e.printStackTrace();
}
return rs;
}
public void close(){
try {
conn.close();
c.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
ResultSet rs;
jdbc conn = new jdbc();
rs=conn.executeQuery("select * from test");
try{
while (rs.next()) {
System.out.println(rs.getString("id"));
System.out.println(rs.getString("name"));
}
}catch(Exception e) {
e.printStackTrace();
}
}
}

2、Class.forName的作用?为什么要用?
答:调用该访问返回一个以字符串指定类名的类的对象。

说出在JSP页面里是怎么分页的?
页面需要保存以下参数:
总行数:根据sql语句得到总行数
每页显示行数:设定值
当前页数:请求参数
页面根据当前页数和每页行数计算出当前页第一行行数,定位结果集到此行,对结果集取出每页显示行数的行即可。

4、在ORACLE大数据量下的分页解决方法。一般用截取ID方法,还有是三层嵌套方法。
答:一种分页方法
<%
int i=1;
int numPages=14;

//获取当前页面
String pages = request.getParameter("page") ;
int currentPage = 1;
currentPage=(pages==null)?(1):{Integer.parseInt(pages)};

//获得记录总数
sql = "select count(*) from tables";
ResultSet rs = DBLink.executeQuery(sql) ;
while(rs.next()) i = rs.getInt(1) ;

//获取总页数
int intPageCount=1;
intPageCount=(i%numPages==0)?(i/numPages):(i/numPages+1);

//设置上下页
int nextPage ;
int upPage;
nextPage = currentPage+1;
if (nextPage>=intPageCount) nextPage=intPageCount;
upPage = currentPage-1;
if (upPage<=1) upPage=1;

//获取数据内容并显示
rs.close();
sql="select * from tables";
rs=DBLink.executeQuery(sql);
i=0;
while((i<numPages*(currentPage-1))&&rs.next()){i++;}
%>
//输出内容
//输出翻页连接
合计:<%=currentPage%>/<%=intPageCount%>
<a href="List.jsp?page=1">第一页</a>
<a href="List.jsp?page=<%=upPage%>">上一页</a>

<%
for(int j=1;j<=intPageCount;j++){
if(currentPage!=j){
%>
//显示所有页面的连接
<a href="list.jsp?page=<%=j%>">[<%=j%>]</a>

<%
}else{
out.println(j);
} //end of if
} //end of for
%>

<a href="List.jsp?page=<%=nextPage%>">下一页</a>
<a href="List.jsp?page=<%=intPageCount%>">最后页 </a>


Xml方面
2、你在项目中用到了xml技术的哪些方面?如何实现的?
答:用到了数据存贮,信息配置两方面。在做数据交换平台时,将不能数据源的数据组装成XML文件,然后将XML文件压缩打包加密后通过网络传送给接收者,接收解密与解压缩后再同XML文件中还原相关信息进行处理。在做软件配置时,利用XML可以很方便的进行,软件的各种配置参数都存贮在XML文件中。

3、用jdom解析xml文件时如何解决中文问题?如何解析?
答:看如下代码,用编码方式加以解决
package test;
import java.io.*;
public class DOMTest {
private String inFile = "c:\\people.xml";
private String outFile = "c:\\people.xml";
public static void main(String args[]){
new DOMTest();
}
public DOMTest() {
try {
javax.xml.parsers.DocumentBuilder builder =
javax.xml.parsers.DocumentBuilderFactory.newInstance().newDocumentBuilder();
org.w3c.dom.Document doc = builder.newDocument();
org.w3c.dom.Element root = doc.createElement("老师");
org.w3c.dom.Element wang = doc.createElement("王");
org.w3c.dom.Element liu = doc.createElement("刘");
wang.appendChild(doc.createTextNode("我是王老师"));
root.appendChild(wang);
doc.appendChild(root);
javax.xml.transform.Transformer transformer =
javax.xml.transform.TransformerFactory.newInstance().newTransformer();

transformer.setOutputProperty(javax.xml.transform.OutputKeys.ENCODING, "gb2312");
transformer.setOutputProperty(javax.xml.transform.OutputKeys.INDENT, "yes");
transformer.transform(new javax.xml.transform.dom.DOMSource(doc),
new javax.xml.transform.stream.StreamResult(outFile));
} catch (Exception e) {
System.out.println (e.getMessage());
}
}
}

4、编程用JAVA解析XML的方式.
答:用SAX方式解析XML,XML文件如下:
<?xml version="1.0" encoding="gb2312"?>
<person>
<name>王小明</name>
<college>信息学院</college>
<telephone>6258113</telephone>
<notes>男,1955年生,博士,95年调入海南大学</notes>
</person>
事件回调类SAXHandler.java
import java.io.*;
import java.util.Hashtable;
import org.xml.sax.*;
public class SAXHandler extends HandlerBase {
private Hashtable table = new Hashtable();
private String currentElement = null;
private String currentvalue = null;
public void setTable(Hashtable table) {
this.table = table;
}
public Hashtable getTable(){
return table;
}
public void startElement(String tag, AttributeList attrs) throws SAXException {
currentElement = tag;
}
public void characters(char[] ch, int start, int length) throws SAXException {
currentvalue = new String(ch, start, length);
}
public void endElement(String name) throws SAXException {
if (currentElement.equals(name)) table.put(currentElement, currentvalue);
}
}

JSP内容显示源码,SaxXml.jsp:
<HTML>
<HEAD>
<title>剖析XML文件people.xml</title>
</HEAD>
<BODY>
<%@ page errorPage="ErrPage.jsp" contentType="text/html;charset=GB2312" %>
<%@ page import="java.io.*" %>
<%@ page import="java.util.Hashtable" %>
<%@ page import="org.w3c.dom.*" %>
<%@ page import="org.xml.sax.*" %>
<%@ page import="javax.xml.parsers.SAXParserFactory" %>
<%@ page import="javax.xml.parsers.SAXParser" %>
<%@ page import="SAXHandler" %>
<%
File file = new File("c:\\people.xml");
FileReader reader = new FileReader(file);
Parser parser;
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser sp = spf.newSAXParser();
SAXHandler handler = new SAXHandler();
sp.parse(new InputSource(reader), handler);
Hashtable hashTable = handler.getTable();
out.println("<TABLE BORDER=2><CAPTION>教师信息表</CAPTION>");
out.println("<TR><TD>姓名</TD>" + "<TD>" +
(String)hashTable.get(new String("name")) + "</TD></TR>");
out.println("<TR><TD>学院</TD>" + "<TD>" +
(String)hashTable.get(new String("college"))+"</TD></TR>");
out.println("<TR><TD>电话</TD>" + "<TD>" +
(String)hashTable.get(new String("telephone")) + "</TD></TR>");
out.println("<TR><TD>备注</TD>" + "<TD>" +
(String)hashTable.get(new String("notes")) + "</TD></TR>");
out.println("</TABLE>");
%>
</BODY>
</HTML>

EJB方面
1、EJB2.0有哪些内容?分别用在什么场合? EJB2.0和EJB1.1的区别?
答:规范内容包括Bean提供者,应用程序装配者,EJB容器,EJB配置工具,EJB服务提供者,系统管理员。这里面,EJB容器是EJB之所以能够运行的核心。EJB容器管理着EJB的创建,撤消,激活,去活,与数据库的连接等等重要的核心工作。JSP,Servlet,EJB,JNDI,JDBC,JMS.....

2、EJB与JAVA BEAN的区别?
JavaBean是可复用的平台独立的软件组件,开发者可以在软件构造器工具中对其直接进行可视化操作。

Enterprise Java Bean 相当于DCOM,即分布式组件。它是基于Java的远程方法调用(RMI)技术的,所以EJB可以被远程访问(跨进程、跨计算机)。但EJB必须被布署在诸如Webspere、WebLogic这样的容器中,EJB客户从不直接访问真正的EJB组件,而是通过其容器访问。EJB容器是EJB组件的代理,EJB组件由容器所创建和管理。客户通过容器来访问真正的EJB组件。

3、EJB的基本架构
答:一个EJB包括三个部分:
Remote Interface 接口的代码
package Beans;
import javax.ejb.EJBObject;
import java.rmi.RemoteException;
public interface Add extends EJBObject {
//some method declare
}

Home Interface 接口的代码
package Beans;
import java.rmi.RemoteException;
import jaax.ejb.CreateException;
import javax.ejb.EJBHome;
public interface AddHome extends EJBHome {
//some method declare
}

EJB类的代码
package Beans;
import java.rmi.RemoteException;
import javax.ejb.SessionBean;
import javx.ejb.SessionContext;
public class AddBean Implements SessionBean {
//some method declare
}

J2EE,MVC方面
1、MVC的各个部分都有那些技术来实现?如何实现?
答:MVC是Model-View-Controller的简写。设计的基本原理是将复杂性分解为三个组件,即模型、视图、控制器。
模型表示数据和处理数据的业务逻辑或应用程序对象。
试图是用户要查看或存取的数据的表示。
控制器定义了用户与模型和试图交互的方式。


2、应用服务器与WEB SERVER的区别?
Web Service 是一种新的分布式技术。一个Web服务本质上是一个应用组件,可以通过Web协议和数据编码机制,例如HTTP和XML,对这个组件进行访问。

Soap简单对象访问协议:
是一种基于XML的通信协议。它包括3个部分。
Soap封装结构:定义消息的XML格式,包括其整体框架、消息内容、由谁处理这些内容等。
Soap编程规则:定义如何将程序数据表示为XML。
Soap RPC表示:定义如何使用scap进行远程过程调用。

WSDL Web服务描述语言:
WSDL文件是一个XML文档,用于说明一组soap消息以及如何交换这些消息。还定义了服务的位置以及使用服务的通信协议等。

Uddi统一描述、发现和集成标准
是wed服务的黄页。它提供了用于服务注册的目录技术,并用它来建立Web服务的目录信息。UDDI的核心组件是UDDI商业注册,它使用一个XML文档来描述企业及所提供的Web服务。它包括3个部分:
白页:介绍提供服务的公司,包括名称、地址和联系方式等;
黄页:包括按照标准分类法进行分类的行业类别;
绿页:详细介绍,访问服务接口等技术信息。

Web服务是构建在soap(简单对象访问协议)、wsdl(web服务描述语言)、uddi(统一描述、发现和集成标准)3个开放的核心标准之上的。Soap用来进行Web服务通信的协议,WSDL用来进行说明和描述Web服务
由于Web服务完全基于XML的,使Web服务成为一个跨语言、跨平台、跨网络的可互操作的分布式应用软件的新平台。
3、J2EE是什么?
J2EE是sun公司推出的一个高层次的全方位、多功能的企业应用开发环境。它包括了当今软件工业界许多最新、最重要的软件技术。J2EE平台包含一整套的服务、应用程序接口和协议,是java技术企业级应用的整体解决方案。J2EE平台通过基于组件的应用程序模型大大简化了开发过程,同时还支持任何分布式体系和多层次的应用开发。随着越来越多的第三方对J2EE的支持和标准认证,J2EE已被广泛用来开发企业级应用软件、中间件和组件软件。
J2EE Java2平台企业版:
1、提供了基于组件的方式来设计、开发、组装和部署企业应用。
2、提供了一个多层次分布式的应用模型,包括了可复用的组件、基于XML数据交换、统一的安全模式以及灵活的事务控制。基于这些技术,可开发出满足市场要求的,基于平台无关的J2EE组件的解决方案。
3、J2EE平台使用的多层分布式应用模型中应用程序主要分为:客户层(Applet)、Web层(Servlet和JSP)、业务层(EJB)、企业信息系统层。


使用类库开发与使用框架包进行开发的区别?
框架包简单的可以认为是一组类和接口,它们相互协作以解决特定类型的软件问题。
类库包含的是应用程序可以调用的函数或例程。而框架包提供通用的、相互协作的组件,应用程序通过扩展这些组件提供特定函数组。应用程序将在这些扩展点进行扩展,运行时这些扩展将被框架系统反调用。这正与使用类库开发的应用程序,运行时的函数调用时颠倒的。

5、BS与CS的联系与区别。
传统的分布式应用程序都是基于Client/Server结构的,而近年来人们发现基于Client/Server结构的应用程序有很多缺点,比如:如果客户端的代码需要改变,那么所有机器上的客户端程序都要重新安装;如果某台机器有了不可修复的损坏,那么得去别的机器上重新安装客户端软件才能够使用。而基于Browser/Server结构的应用程序就没有以上的缺点了,我们可以使用任何一台有浏览器的机器来工作,而因为所有的程序逻辑都在服务器端,所以服务器端的代码变动不需要作为客户端的浏览器再做任何工作。

6、STRUTS的应用(如STRUTS架构)
答:Struts是采用Java Servlet/JavaServer Pages技术,开发Web应用程序的开放源码的framework。 采用Struts能开发出基于MVC(Model-View-Controller)设计模式的应用构架。 Struts有如下的主要功能:
一.包含一个controller servlet,能将用户的请求发送到相应的Action对象。
二.JSP自由tag库,并且在controller servlet中提供关联支持,帮助开发员创建交互式表单应用。
三.提供了一系列实用对象:XML处理、通过Java reflection APIs自动处理JavaBeans属性、国际化的提示和消息。

设计模式方面
1、开发中都用到了那些设计模式?用在什么场合?
答:人们在自己的环境中不断发现问题和寻找问题的解决方案的时候,发现有一些问题及其解决方案不断变换面孔重复出现,但在这些不同的面孔后面有着共同的本质,这些共同的本质就是模式。设计模式就是用来描述解决这些问题的解决方案的核心的。

工厂模式
专门负责将大量有共同接口的类实例化。工厂模式可以动态确定将那一个类实例化,不必事先知道每次要实例化那一个类。

简单工厂模式
或称静态工厂方法模式。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式就是由一个工厂类根据传入的参数决定创建那一种产品类的实例。
简单工厂模式涉及到工厂角色、抽象产品角色以及具体产品角色:l工厂类角色:含有与应用紧密相关的商业逻辑。工厂类在客户端的直接调用下创建产品对象。l抽象产品角色:担任这个角色的类是由工厂方法模式所创建的对象的父类,或它们共同拥有的接口。l具体产品角色:工厂方法模式所创建的任何对象都是这个角色的实例。
优点是:允许客户端相对独立于产品创建的过程,并且在系统引入新产品的时候无需修改客户端。缺点是:如果有新的产品加入到系统中去,就需要修改工厂类,将必要的逻辑加入到工厂类中。
工厂方法模式
或称多态性工厂模式。工厂方法模式的用意是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类中。工厂方法模式中,核心的工厂类不再负责所有的产品的创建,而是将具体创建的工作交给子类去做。它仅负责给出具体工厂子类必须实现的接口。这样可以用来允许系统在不修改具体工厂角色的情况下引进新的产品。
工厂方法模式涉及到的角色:l抽象工厂角色:它不包含应用逻辑。任何在模式中创建对象的工厂类必须实现这个接口。l具体工厂角色:含有与应用密切相关的逻辑,并且受到应用程序的调用以创建产品对象。l抽象产品角色:工厂方法模式所创建的对象的超类型,也就是产品对象的共同父类或共同拥有的接口。l具体产品角色:这个角色实现了抽象产品角色所声明的接口。
单例模式
确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
特点:单例类只能有一个实例;单例类必须自己创建自己的惟一的实例;单例类必须给所有其他对象提供这一实例。
多例模式
多例类可以有多个实例,并且多例类必须自己创建、管理自己的实例,并向外界提供自己的实例。
在系统中可以用于数据库连接池、键值缓存等。
代理模式
给某个对象提供一个代理对象,并由代理对象控制对原对象的引用。
代理模式所涉及的角色:抽象主题角色:声明了真实主题和代理主题的共同接口,这样一来在任何可以使用真实主题的地方都可以使用代理主题角色。

名称

 

2、UML方面
UML包括的图有:案例图、类图、序列图、合作图、状态图、活动图、构件图、部署图。

类图中的关系有:
一般关系(类于类的继承关系、接口与接口的继承关系、类对接口的实现关系);
关联关系:它使一个类知道另一个类的属性和方法。在java中,使用实例变量实现。
聚合关系:是整体与个体之间的关系。也是使用实例变量实现。
合成关系:是比聚合关系强的关系。它要求普通的聚合关系中代表整体的对象负责代表部分的对象的生命周期。
依赖关系:总是单向的。表示一个类依赖于另一个类的定义。

3、软件的可维护性与可复用性
一个好的系统设计应该有如下性质:
可扩展性:新的性能可以很容易地加入到系统中。
灵活性:可以允许代码修改平稳地发生、而不会波及到很多其他的模块。
可插入性:可以很容易地将一个类抽出去,同时将另一个有同样接口的类加入进来。

在java中可以给出一个或多个抽象java类或java接口,规定出所有的具体类必须提供的方法特征作为系统设计的抽象层。这个抽象层预见了所有的可能扩展,因此,在任何扩展情况下都不会改变。

接口是实现构件的可插入性的关键。一个java接口是一些方法特征的集合,这些方法一般都是在系统经常出现的方法。一个接口只有方法的特征,没有方法的实现,因此在不同地方的该方法实现,可以具有不同的行为。
接口是对可插入性的保证:
因为在类的关联中,如果一个关联不是针对一个具体类的,而是针对一个接口的,那么任何实现这个接口的类就都可以满足要求。当前对象并不在意所关联的是哪个具体类,而仅仅关心这个类是否实现了某个接口。这样一来,就可以动态地将这个关联从一个具体类转换到另一个具体类,而这样做的唯一条件是它们都实现某个接口。

抽象类仅提供一个类型的部分实现。抽象类通常代表一个抽象概念,它提供一个继承的出发点。
javascript方面
1、如何校验数字型?
var re=/^\d{1,8}$|\.\d{1,2}$/;
var str=document.form1.all(i).value;
var r=str.match(re);
if (r==null) {
sign=-4;
break;
} else{
document.form1.all(i).value=parseFloat(str);
}

CORBA方面
什么是RMI?
Java RMI(Remote Method Invocation)--Java的远程方法调用是Java所特有的分布式计算技术,它允许运行在一个Java虚拟机上的对象调用运行在另一个Java虚拟机上的对象的方法,从而使Java编程人员可以方便地在网络环境中作分布式计算。面向对象设计要求每个任务由最适合该任务的对象执行,RMI将这个概念更深入了一步,使任务可以在最适合该任务的机器上完成。
RMI定义了一组远程接口,可以用于生成远程对象。客户机可以象调用本地对象的方法一样用相同的语法调用远程对象。RMI API提供的类和方法可以处理所有访问远程方法的基础通信和参数引用要求的串行化。
使用RMI开发步骤:
1、定义一个远程接口(远程接口必须继承接口,每个方法必须抛出远程异常,方法参数和方法返回值都必须是可序列化的)
2、实现远程接口
3、定义使用远程对象的客户程序
4、产生远程访问对象的桩和框
5、注册远程对象
6、运行服务器和客户程序

RMI和CORBA的区别?
远程方法调用(RMI)和CORBA都是分布式计算技术,在进行分布式时各有其优缺点,CORBA和RMI的区别。
  CORBA(Common Object Request Broker Architecture)是OMG的Object Management Architecture(对象管理结构),它是面向对象的分布式系统建立所依据的标准。CORBA被设计成一个能供所有编程语言使用的一个开放性说明,就是说一个机器上的Java客户可以要求另一个用SmallTalk或C++的机器服务。正是由于这种语言的独立性使得CORBA这么灵活和吸引人。为了适应语言独立性,CORBA采用了非常通用的标准作为其接口。在不同的语言中,远程调用、签名和对象的引入有各自不同的定义,所以CORBA必须尽可能的中立和开放。正是这种通用性是CORBA的一个弱点。当开发人员都采用CORBA时,他们要用一种新的标准定义语言接口,它要求开发者学习新的编程接口,从而减小了远程模型的透明性。
  RMI是为仅在Java对Java的分布式计算中而开发的。远程调用的标准是为了Java和应用Java的自然Java签名和调用而开发的,这使得RMI对Java的开发者相当透明而且易于实现。RMI用Java语言紧密集成从而同CORBA相比能够提供非常好的容错能力及对异常的处理。尽管Java的RMI标准不像CORBA那样语言独立,但Java本身是一个独立的平台,这就使RMI在跨平台的分布软件开发中是一个很好的选择。
  RMI是Java语言在分布式计算上的基本模型,很多Java的分布式系统,包括我们本章要涉及的EJB,都是建立在RMI的思想上的。

基于IIOP协议的远程方法调用(RMI-IIOP)
RMI是一个分布对象系统,允许java对象与运行在其他虚拟机上的java对象进行交互。使得可以象访问本地对象一样访问远程对象;只要获得一个远程对象的引用,就可以把这个对象看作如同运行在同一虚拟机上那样来调用它的方法。但RMI是一个仅限于Java的分布式对象系统,这个系统使用了一个java特有的传输协议,即java远程方法协议(JRMP),在客户端和服务器之间进行信息传输。然而,这也意味着使用这种协议只能访问其他java对象,而无法访问非java对象。
远程方法调用的实际处理过程与CORBA的过程相似,即RMI使用客户端桩和服务器端框。要调用远程方法,客户端首先在桩上生成一个请求,然后将此请求传递给服务器,在服务器的框将请求转换成对远程对象的实际方法调用。客户端桩将远程方法的所有参数序列化后传递给服务器框,框将对参数反序列化。
但是由于这种协议不支持EJB需要的企业级交互,因为在这种类型的交互中必须通过远程方法调用来传递事务和安全环境。为此sun公司创建了RMI-IIOP即基于因特网内部对象请求代理协议之上的远程方法调用。IIOP是一个用在CORBA对象请求代理间进行通信的协议,在IIOP之上的RMI同时具有RMI和CORBA技术的特点。

LINUX方面
1、LINUX下线程,GDI类的解释。
答:LINUX实现的就是基于核心轻量级进程的"一对一"线程模型,一个线程实体对应一个核心轻量级进程,而线程之间的管理在核外函数库中实现。
GDI类为图像设备编程接口类库。

posted @ 2006-07-04 08:02 多力宇扬 阅读(1052) | 评论 (0)编辑 收藏

                                                控制器组件 -- ActionServlet

我们知道 Struts 的入口是 ActionServlet. org.apache.struts.ActionServlet 类在 Struts 应用程序中负责拦截工作。所有来自客户层的请求,在交给应用程序处理之前,都会先经过 ActionServlet ActionServlet 的一个实例接受到一个 HttpRequest 对象时,无论这是通过 doGet() 方法还是 doPost() 方法受到的 , 都会调用 process() 方法来处理该请求。 ActionServlet process() 方法如下所示 :

Protected void process(HttpServletRequest request,HttpServletResponse response) throws IOException,ServletExcepion

{

RequestUtils.selectModule(request,getServletContext());

getRequestProcessor(getModuleConfig(request)).process(request,response);

}

尽管 process() 方法看起来并不复杂,但是它调用的方法却很复杂。首先,它会调用 org.apache.struts.util.RequestUtils 类的静态方法 selectModule(), 并把当前的请求和这个 Web 应用程序的 ServletContext 都传入该方法。 selectModule() 方法的工作是将 request.getServletContext() 返回的路径与每个配置应用模块的前缀相匹配,从而选出处理当前请求的应用模块。

: 如果你只用到了一个 Struts 配置文件 , 那么你就只会有一个应用程序,也就是默认的应用程序。为了让默认的应用程序和应用模块能够简单而一致的处理请求,默认应用程序可视为一个应用模块。因此 , 任何请求只要不含应用程序的后缀 (suffix), 都会被传送给默认的应用程序 , 由其处理。

扩展 ActionServlet

尽管 Struts 框架仍然允许你扩展 ActionServlet 类,但是这么做的好处已大不入前,因为它的大部分功能都已经放到新的 RequestProcessor 类里了。如果你仍然想扩展自己的 ActionSerlvet 类,那么只要创建一个扩展了 ActionServlet 的类并配置 Struts 框架让它使用你的类就可以了。看以下一个覆盖了 init() 方法的类。

 

Package dory.doo.framework;

import javax.servlet.ServeltException;

import javax.sertlvet.UnaviableException;

import org.apache.struts.action.ActionServlet;

import dory.doo.strutus.service.IStorefrontService;

import dory.doo.strutus.service.StorefrontServiceImpl;

import dory.doo.strutus.framework.util.IConstants;

import dory.doo.strutus.framework.exceptions.DatastoreException;

/**

* 扩展了 Struts ActionServlet, 以此来完成你自己特殊的初始化工作

*/

public class ExtendedActionServlet extends ActionServlet

 {

   public void init() throws ServletException

{

  // 确定你先调用了超类

  super.init();

  // 初始化持久存储服务

  try

   {

     // 创建服务接口的一个实例

     IStorefrontService serviceImpl=new StorefrontServiceImpl();

     // 把服务对象存储到应用作用域类

     getServletContext().setAttribute(IConstants.SERVICE_INTERPACE_KEY,serviceImpl);

   }

  catch(DatastoreException ex)

   {

     // 如果服务对象的初始化工作出了问题,就关闭 web 应用程序

     ex.printStackTrace();

     throw new UnavailableException(ex.getMessage());

   }

    }

 }

覆盖 init() 方法只是一个例子 , 你可以覆盖任何你想覆盖的方法 , 如果真的需要覆盖 init() 方法 , 请确定你先调用了 super.init() 方法 , 这样才会完成默认的初始化工作。

要使用自己的 ActionServlet 子类,那么必须将 web.xml 修改如下 :

 <servlet>

   <servlet-name>MyActionServlet</servlt-name>

   <servlet-class>dory.doo.framework. ExtendedActionServlet</servlet-class>

 </servlet>

Struts 初始化过程

web.xml 文件中配置的初始化参数而定, servlet 容器首次启动时 , 或者第一个对比 servlet 的请求来到时 ,servlet 容器就会加载 Stuts ActionServlet. 无论是哪种情况 ( 也不管是什么样的 Java Servlet) ,都一定要保证 inint() 得到调用,而且必须在 servlet 处理任何请求之前完成。 Struts 框架在 init() 被调用时 , 会做好所有的初始化工作。看看如下就知道了它到底干了些什么 :

1.       Struts 框架内部的消息资源包进行初始化。这些消息资源包是用来向日志文件传输信息性,警示和错误消息的 . org.apache.struts.action.ActionResources 资源包 ( /org/acache/struts/action/ActionResources.properties 文件 ) 则用来取得这些内部消息。

2.       web.xml 文件加载控制 ActionServlet 类各项行为的初始化参数。这些参数包括 config,debug,detail 以及 convertNull

3.       web.xml 文件加载 servlet 名和 servlet 映射信息,并进行初始化。这些值可供整个 Struts 框架使用 ( 几乎都是给 JSP 标记库使用 ), 以便在 HTML 表单提交时,输出正确的 URL 目标。在此初始化期间, Struts 框架给所有使用 DTD 也会得到注册。 DTD 接下来可以用于严正配置文件。

4.       加载默认应用程序的 Struts 配置数据,并进行初始化,这些配置数据由 config 初始化参数来指定。默认的 Struts 配置文件得到解析后,会创建一个 ApplicationConfig 对象,并存储在 ServletContext 对象中。默认应用程序的 ApplicationConfig 对象会以 org.apache.struts.action.APPLICATION 这个键值存储在 ServeltContext 对象中。

5.       Struts 配置文件中为默认应用程序指定的每个消息资源都会被加载,初始化,并存储在 ServletContext 对象中适当位置 ( 依每个 message-resources 元素中指定的 key 属性而定 ) 。如果没有指定 key 属性,那么相应的消息资源会键值 org.apache.struts.action.MESSAGE 来存储。只有一个消息资源可作为默认消息资源存储,因为每个键都必须是唯一的。

6.       Struts 配置文件中所声明的每个数据源都被会被加载并初始化。如果没有指定任何 data-sources 元素,则会跳过这个步骤。

7.       Struts 配置文件中所指定的每个 plug-in( 插件 ) 元素都会被加载和初始化。对于每个 plug-in 元素所指定的类,其 itit() 方法都将被调用。

8.       一旦默认应用程序正确地完成了初始化之后, servlet init() 方法会确定是否指定了任何其他的应用模块,如果有的话,对于每个应用模块都要重复步骤 4-7

: 为了达到更好的性能,你可能会尝试为一个应用程序建立多个 Struts 控制器 servlet 。这么做几乎得不到更好的性能或扩展性, Struts 设计者也不认为这是一个好注意。 Servlet 是多线程的,因此可以让多个客户同时执行。一个 servlet 就能同时为多个客户提供服务。

 

posted @ 2006-06-30 10:14 多力宇扬 阅读(953) | 评论 (0)编辑 收藏

在web应用中实施过滤是我们常用的技术,通过过滤,可以对请求进行统一编码,对请求进行认证等.每个Fillter可能只担任很少的任务,多个Filter可以互相协作,通过这种协作,可以完成一个复杂的功能.

Fileter
声明: public interface Filter
它是Filter必须实现的接口,它包含一下的方法
. init(FilterConfig config): 这个方法初始化Filter.
. doFilter(ServletRequest request,ServletResponse,FilterChain chain): Filter的业务方法就在这里实现.
. destory(): 释放Filter占用的资源.

FilterChain
声明: public interface FilterChain
它是代码的过滤链,通过这个接口把过滤的任务在不同的Filter之间转移.它包含一个方法:
doFilter(ServletRequest,request,ServletResponse response)
通过这个方法来调用下一下Filter,如果没有吓一个Filter,那么将调用目标资源.

FilterConfig
声明: public interface FilterConfig
代表了Filter的配置,和Servlet一样,Servlet也有一些配置信息,比如名字和初始化参数等.
它包含以下的方法.
.getFilterName(): 返回Filter的名字.
.getInitParameter(String name): 获得名称为name的初始化参数
.getServletContext(): 返回这个Filter所在Servlet上下文对象.
.getInitParameterNames(): 获得Filter配置中的所有初始化参数的名字.

过滤器主要对客户端的请求和客户端的响应进行统一处理.最常见的web过滤器有权限认证过滤器,字符编码过滤器,图象处理过滤器等.

字符编码过滤器(EncodingFillter.java)
package dorydoo.util;

import javax.servlet.FilterChain;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletException;
import javax.servlet.FilterConfig;
/**
 *
 * @author Dory Doo
 */
public class EncodingFillter implements Filter
{
    protected FilterConfig filterConfig;
    private String targetEncoding="gb2312";
    /**
     *初始化过滤器像一般的Servlet一样,它也可以获得初始化参数
    */
    public void init(FilterConfig config)throws ServletException
    {
        this.filterConfig=config;
        this.targetEncoding=config.getInitParameter("encoding");
    }
    /**
     *进行过滤处理,最最要的地方就是这里了
    */
    public void doFilter(ServletRequest srequest,ServletResponse sresponse,FilterChain chain)
    throws IOException,ServletException
    {
        System.out.println("使用以下方法进行编码:encoding="+targetEncoding);
       
        HttpServletRequest request=(HttpServletRequest)srequest;
        request.setCharacterEncoding(targetEncoding);
        //把处理权发送到下一个
        chain.doFilter(srequest,sresponse);
    }
   
    public void setFilterConfig(final FilterConfig filterConfig)
    {
        this.filterConfig=filterConfig;
    }
    //销毁过滤器
    public void destroy()
    {
        this.filterConfig=null;
    }
}
然后在web.xml中配置我们的应用.
 <web-app>
      .................
        <!--Filter Config-->
       <filter>
            <filter-name>cncoding</filter-name>
            <filter-class>dorydoo.util.EncodingFilter</filter-class>
            <init-param>
                <param-name>encoding</param-name>
                <param-value>gb2312</param-value>
            </init-param>
        </filter>  
        <filter-mapping>
            <filter-name>encoding</filter-name>
            <servlet-name>action</servlet-name>
        </filter-mapping> 
        <filter-mapping>
            <filter-name>encoding</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
      ........
 </web-app>


在来看一用户认证的过滤器(SignonFilter)
package dorydoo.util;

import javax.servlet.FilterChain;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletException;
import javax.servlet.FilterConfig;
import javax.servlet.http.HttpSession;
/**
 *
 * @author DuYang
 */
public class SignonFilter implements Filter
{
    protected FilterConfig filterConfig;
    String LOGIN_PAGE="login.jsp";
    /**
     *初始化过滤器像一般的Servlet一样,它也可以获得初始化参数
    */
    public void init(FilterConfig config)throws ServletException
    {
        this.filterConfig=config;
    }
    /**
     *进行过滤处理,最最要的地方就是这里了
    */
    public void doFilter(final ServletRequest req,final ServletResponse res,FilterChain chain)
    throws IOException,ServletException
    {    
        HttpServletRequest hreq=(HttpServletRequest)req;
        HttpServletResponse hres=(HttpServletResponse)res;
        HttpSession session=hreq.getSession();
        String isLogin="";
        try
        {
            isLogin=(String)session.getAttribute("isLogin");
            if(isLogin.equals("true"))
            {
                System.out.println("在SignonFilter中验证通过");
                //验证通过继续处理
                chain.doFilter(req,res);
            }
            else
            {
                //验证不成功重新登录
                hres.sendRedirect(LOGIN_PAGE);
                System.out.println("被SignonFilter拦截一个为认证的请求");
            }
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }
   
    public void setFilterConfig(final FilterConfig filterConfig)
    {
        this.filterConfig=filterConfig;
    }
    //销毁过滤器
    public void destroy()
    {
        this.filterConfig=null;
    }
}
在SignonFilter的doFilter()方法中,首先通过isLogin=(String)session.getAttribute("isLogin");判断是否登录用户,如果不是则返回到login页面.配置web.xml文件就和上面的基本上没什么差别.

posted @ 2006-06-29 11:23 多力宇扬 阅读(279) | 评论 (0)编辑 收藏

因为自己获得过别人的帮助,所以把自己的资源拿出来帮助别人,如果你需要这些资源,请留下email,我会在晚上一起发送给大家,这次分享的资源目录如下:(里面的都是我测试好了,都已经下载到我的本地机器上了的,所以大家放心,可能有的比较慢,还有大家需要自己去寻找最好的下载时间,因为我在下载张孝详老师的讲座的时候有的课程就比较慢有的就很快130KB/s),如果需要就赶紧吧,因为有的服务器不大稳定.
contents:
(1) MySQL数据库教程光盘
(2) LINUX视屏教程
(3).面向对象程序设计
(4).张孝详JavaScript视频讲座
(5).动态网页设计(ASP+JSP+PHP)
(6).JSP程序设计
(7).Eclipse基础教程
(8).HTML语言速成
(9).HTML协议教程
(9).xml_asp_学习光盘
(10)JAVA程序设计计算
(11)WEB应用系统设计[32讲]

暂时就分享到这里吧,以后有空了在和大家分享,有问题请博客留言或者mail To me ^_^!大多数我在下载的时候速度都达到了130KB/s,只有少数几个课程比较慢一点!例外我只能以邮件附件的形式发送给大家,请大家放心绝对安全,呵呵!

posted @ 2006-06-28 10:52 多力宇扬 阅读(852) | 评论 (10)编辑 收藏

  Tomcat从5.x开始就可以在server.xml里配置数据源,后来用到了Proxool对比了一下觉得Proxool更方便更好用,它提供了更多的方法,简单,推荐大家使用.
  下载地址:http://proxool.sourceforge.net/ 最新版本为: Proxool 0.9.0RC2
  下载后解压缩Proxool 0.9.0RC2后,把Proxool 0.9.0RC2/lib下的.jar文件部署到WEB-INF/lib下.
  看看下面的范例(example for Oracle):
  Proxool.jsp

<%@ page import="java.sql.*"%>
<%@ page contentType="text/html;charset=gb2312"%>

<html>
    <head>
        <title>Proxool.jsp</title>
    </head>
    <body>
        <h2>使用Proxool.jsp</h2>
        <%
           Connection con=null;
           Statement stmt=null;
           ResultSet rs=null;
           
           String ename="";
           
           try
           {
             Class.forName("org.logicalcobwebs.proxool.ProxoolDriver");
             con=DriverManager.getConnection("proxool.JSPBook:oracle.jdbc.driver.OracleDriver:
                       jdbc:oracle:thin:@yang:1521:orcl","scott","ss");             
             stmt=con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
                                      ResultSet.CONCUR_UPDATABLE);
             String query="select * from emp";
             rs=stmt.executeQuery(query);
             while(rs.next())
             {
               ename=rs.getString("ename");
      %>
        从emp表中取出姓名<%=ename%><br>
      <%
             }
             stmt.close();
             con.close();
           }
           catch(SQLException e)
           {
             out.println("发生异常"+e);
           }
           finally
           {
             try
             {
               if(con!=null)
               {
                 con.close();
               }
             }
             catch(SQLException ne)
             {
               out.println("SQLException:"+ne);
             }
           }
        %>
    </bdoy>
</html>
Proxool.jsp通过Proxool连接池取得Connection,然后显示emp表格中的ename.
首先动态加载Proxool的driver:
  Class.forName("org.logicalcobwebs.proxool.ProxoolDriver);
然后将Proxool URL分为三个部分: 连接池的别名,JDBC驱动程序(DataBase JDBC Drivers),连接URL.

设定Proxool
proxool提供了许多连接池的参数,例如:连接池最多有几个Connection,最少有几个Connection,Connection生命期限等等。
Proxool主要有以下四种设定方式:
(一) 通过java.util.Properties对象来设定,例如:
Properties info=new Properties();
info.setProperty("proxool.maximum-connection-count","20");
info.setProperty("proxool.house-keeping-test-sql","select CURRENT_DATE");
info.setProperty("user","your DB username");
info.setProperty("password","your DB prassword");
String alias="Develop"; //Proxool连接池的别名,根据自己喜好随便写^_^
String driverClass="oracle.jdbc.driver.OracleDriver";
String driverUrl="jdbc:oracle:thin:@127.0.0.1:1521:DatabaseName";
String url="proxool."+alias+":"+drvierClass+":"+driverUrl;
connection=DrvierManager.getConnection(rul,info);

(二) 通过XML文件来设定,例如:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!--the proxool configuration can be embedded within your own application's. Anything outside the "proxool" tag is ignored.-->
<proxool>
  <alias>Develop</alias>
  <driver-url>
    jdbc:oracle:thin:@127.0.0.1:1521:DatabaseName
  </driver-url>
  <driver-class>oracle.jdbc.driver.OracleDriver</driver-class>
  <driver-properties>
    <property name="user" value="your database name"/>
    <property name="password" value="your DB password"/>
  </driver-properties>
  <maximum-connection-count>10</maximum-connection-count>
  <house-keeping-test-sql>select CURRENT_DATE</house-keeping-test-sql>
</proxool>
然后通过JAXPConfiguration读取XML文件:
JAXPConfigurator.configure("/WEB-INF/classes/proxool.xml",false);

(三) 先通过Properties文件来设定,例如:
jdbc-0.proxool.alias=Develop
jdbc-0.proxool.drvier-url=jdbc:oracle:thin:@127.0.0.1:1521:DatabaseName
jdbc-0.proxool.driver-class=oracle.jdbc.driver.OracleDriver;
jdbc-0.user=your database username
jdbc-0.password=your database password
jdbc-0.proxool.maximum-connection-count=10
jdbc-0.proxool.house-keeping-test-sql=select CURRENT_DATE
然后通过PropertyConfigurator读取Properties文件:
PropertyConfigurator.configure("/WEB-INF/classes/Proxool.properties");

(四)在web.xml中,通过servlet来设定.方法又有三种,前两种是按照格式来的:
1.XML文件
<servlet>
  <servlet-name>ServletConfigurator</servlet-name>
  <servlet-class>
     org.logicalcobwebs.proxool.configuration.ServletConfigurator
  </servlet-class>
  <init-param>
     <param-name>xmlFile</param-name>
     <param-value>WEB-INF/classes/Proxool.xml</param-value>
  </init-param>
  <load-on-start>1</load-on-start>
</servlet>

2.Properties文件
<servlet>
  <servlet-name>ServletConfigurator</servlet-name>
  <servlet-class>
     org.logicalcobwebs.proxool.configuration.ServletConfigurator
  </servlet-class>
  <init-param>
     <param-name>propertyFile</param-name>
     <param-value>WEB-INF/classes/Proxool.properties</param-value>
  </init-param>
  <load-on-start>1</load-on-start>
</servlet>

3.Init Prameter
<servlet>
  <servlet-name>ServletConfigurator</servlet-name>
  <servlet-class>
     org.logicalcobwebs.proxool.configuration.ServletConfigurator
  </servlet-class>
  <init-param>
     <init-name>jdbc-0.proxool.alias</init-param>
     <init-value>Develop</init-value>
  </init-param>
  <init-param>
     <init-name>jdbc-0.proxool.driver-rul</init-param>
     <init-value>
        jdbc:oracle:thin:@127.0.0.1:1521:DatabaseName
     </init-value>
  </init-param>
  <init-param>
     <init-name>jdbc-0.proxool.driver-class</init-param>
     <init-value>oracle.jdbc.driver.OracleDriver</init-value>
  <init-param>
</servlet>

建议大家使用第四种方法,好处在于当Container启动时,Proxool的参数会自动设定加载到内存中,原因在于:
<servlet>
......略
<load-on-start>1</load-on-start>

一个完整的示例如下:
web.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app 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/web-app_2_4.xsd"
         version="2.4">
.......略
  <servlet>
     <servlet-name>ServletConfigurator</servlet-name>
     <servlet-class>
       org.logicalcobwebs.proxool.configuration.ServletConfigurator
     </servlet-class>
     <init-param>
       <param-name>propertyFile</param-name>
       <param-value>WEB-INF/classes/Proxool.properties</param-value>
     </init-param>
     <load-on-start>1</load-on-start>
  </servlet>
.......略
</web-app>

Proxool.proterties
jdbc-0.proxool.alias=Develop
jdbc-0.proxool.driver-class=oracle.jdbc.driver.OracleDriver
jdbc-0.proxool.driver.url=jdbc:oracle:thin:@127.0.0.1:1521:DatabaseName
jdbc-0.proxool.maximum-connection-count=10
jdbc-0.proxool.prototype-count=4
jdbc-0.proxool.house-keeping-test-sql=select CURRENT_DATE
jdbc=0.proxool.verbose=true

我们可以用下面的Test Page来进行测试
Proxool-config.jsp
____________________________________________________
<%@ page import="java.sql.*"%>
<%@ page contentType="text/html;charset=gb2312"%>

<html>
    <head>
        <title>Proxool.jsp</title>
    </head>
    <body>
        <h2>使用Proxool.jsp</h2>
        <%
           Connection con=null;
           Statement stmt=null;
           ResultSet rs=null;
           
           String ename="";
           
           try
           {
             con=DriverManager.getConnection("proxool.Develop");             
             stmt=con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
                                      ResultSet.CONCUR_UPDATABLE);
             String query="select * from emp";
             rs=stmt.executeQuery(query);
             while(rs.next())
             {
               ename=rs.getString("ename");
      %>
        从emp表中取出姓名<%=ename%><br>
      <%
             }
             stmt.close();
             con.close();
           }
           catch(SQLException e)
           {
             out.println("发生异常"+e);
           }
           finally
           {
             try
             {
               if(con!=null)
               {
                 con.close();
               }
             }
             catch(SQLException ne)
             {
               out.println("SQLException:"+ne);
             }
           }
        %>
    </bdoy>
</html>
测试结果为:
=====================================
使用Proxool.jsp
从emp表中取出姓名SMITH
从emp表中取出姓名ALLEN
从emp表中取出姓名WARD
从emp表中取出姓名JONES
从emp表中取出姓名MARTIN
从emp表中取出姓名BLAKE
从emp表中取出姓名CLARK
从emp表中取出姓名SCOTT
从emp表中取出姓名KING
从emp表中取出姓名TURNER
从emp表中取出姓名ADAMS
从emp表中取出姓名JAMES
从emp表中取出姓名FORD
从emp表中取出姓名MILLER
从emp表中取出姓名feiyang
从emp表中取出姓名yang
从emp表中取出姓名feifei
从emp表中取出姓名fei

posted @ 2006-06-28 09:51 多力宇扬 阅读(584) | 评论 (0)编辑 收藏

Tomcat下JNDI的配置

    JNDI全名为Java Naming and Directory Interface.JNDI主要提供应用程序所需要资源上命名与目录服务.在Java EE环境中,JNDI扮演了一个很重要的角色,
它提供了一个接口让用户在不知道资源所在位置的情形下,取得该资源服务.
    就好比网络磁盘驱动器的功能一样。如果有人事先将另一台机器上的磁盘驱动器接到用户的机器上,用户在使用的时候根本就分辨不出现在的驱动器是存在本端,
还是在另一端的机器上,用户只需取得资源来用,根本就不知道资源在什么地方。
    JNDI这个接口基本上是LDAP,LDAP全名为Lightweight Directory Access Protocol.
    
    要设定JNDI的JDBC数据源和DBCP连接池需要做以下的工作:(for example Oracle DataBase)

    一. 安装JDBC Driver
    将你DB的JDBC Driver部署到{Tomcat_Install]\common\lib目录下。
    二. 设定Tomcat下的server.xml
    修改{Tomcat_Install|\conf\server.xml文件中你的站台标签里的<Host></Host>之间的内容.如下:
    server.xml
     <Host>
        <Context path="/Develop" docBase="Develop" debug="0" reloadable="true"               crossContext="true">
        <Resource name="jdbc/dy" auth="Container" type="javax.sql.DataSource"/>
            <ResourceParams name="jdbc/dy">
               <parameter>
                  <name>factory</name>
                  <value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
               </parameter>
               <parameter>
                  <name>driverClassName</name>
                  <value>oracle.jdbc.driver.OracleDriver</value>
               </parameter>
               <parameter>
                  <name>url</name>
                  <value>jdbc:oracle:thin:@yang:1521:orcl</value>
               </parameter>               
               <parameter>
                  <name>username</name>
                  <value>scott</value>
               </parameter>
               <parameter>
                  <name>password</name>
                  <value>ss</value>
               </parameter>
               <parameter>
                  <name>maxActive</name>
                  <value>20</value>
               </parameter>
               <parameter>
                  <name>maxIdle</name>
                  <value>10</value>
               </parameter>
               <parameter>
                  <name>maxWait</name>
                  <value>-1</value>
               </parameter>                                                                 
            </ResourceParams>
        </Context>
      </Host>
  上述社定所表示的意思是在Develop站台中,定义一个JDBC数据来源,名称为jdbc/dy.
  通过以下的代码来设置的这个jdbc/dy的数据来源和DBCP连接池:
  <parameter>
     <name>factory</name>
     <value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
  </parameter>
  设定使用DBCP连接池,这是有Jakarta Project组织所制定的连接池程序,它一样是OpenSource的.
参数说明:
     <Context></Context>用于设置你的站台.
     <Context>标签中的path="/Develop"代表网站名称,即: http://IP_DomaninName/Develop; docBase="Develop"代表站台的目录位置,debug则是设定debug level
     ,0表示提供最少的信息,9表示提供最都多的信息;reloadable则表示Tomcat执行时,当class,web.xml被更新时,都会自动重新加载,不需要重新启动Tomcat;
     maxActive表示连接池的最大数据库连接数;设为0表示无限制;maxIdle表示设定连接池中最小能有几个Connection,若为0表示不限制;maxWait 最大建立连接等待时间。
    如果超过此时间将接到异常,设为-1表示无限制,单位为ms;driverClassName JDBC驱动程序;url表示数据库连接字符串.

 三. 设定应用站台中的web.xml
 eg:设定Develop的web.xml如下:
  <resource-ref>
     <description>JNDI JDBC DataSource of Develop</description>   //一个描述
     <res-ref-name>jdbc/dy</res-ref-name>                        //这里必须为你之前指定的<ResourceParams name="jdbc/dy">
     <res-type>javax.sql.DataSource</res-type>
     <res-auth>Container</res-auth>
  </resource-ref>

 四. 使用JDBC数据来源获得Connection对象
   Context initContext=new InitialContext();
   Context envContext=(Context)initContext.lookup("java:/comp/env");
   或者
   Context envContext=(Context)initContext.lookup("java:comp/env");
   DataSourceds conn=(DataSource)envContext.lookup("jdbc/dy");
   conn=ds.getConnection();

按照这四个步骤做下来后,那么你就可以写个Test Page来测试一下了.
Test Page1:
_________________________________________________________________________________________________________
testpool.jsp
<!--测试JNID数据源的配置-->
<%@ page contentType="text/html;charset=gb2312"%>
<%@ page import="javax.naming.Context"%>
<%@ page import="javax.sql.DataSource"%>
<%@ page import="javax.naming.InitialContext"%>
<%@ page import="java.sql.*"%>
<%
  DataSource ds=null;
  try
  {
      Context initCtx=new InitialContext();
      Context envCtx=(Context)initCtx.lookup("java:comp/env");
      //从Context中loopup 数据源
      ds=(DataSource)envCtx.lookup("jdbc/dy");
      if(ds!=null)
      {
        out.println("已经获得DataSource!");
        out.println("<br>");
        Connection conn=ds.getConnection();
        Statement stmt=conn.createStatement();
        ResultSet rst=stmt.executeQuery("select * from emp");
        out.println("以下是从数据库里读出来的数据");
        out.println("<hr>");
        while(rst.next())
        {
          out.println("empName:"+rst.getString("ename"));
          out.println("<br>");
        }
      }
    else
        out.println("连接失败");
  }
  catch(Exception e)
  {
      out.println(e);
  }
%>
如果成功那么输出结果:
========================================
已经获得DataSource!
以下是从数据库里读出来的数据:
empName:SMITH
empName:ALLEN
empName:WARD
empName:JONES
empName:MARTIN
empName:BLAKE
empName:CLARK
empName:SCOTT
empName:KING
empName:TURNER
empName:ADAMS
empName:JAMES
empName:FORD
empName:MILLER
empName:feiyang
empName:yang
empName:feifei
empName:fei

posted @ 2006-06-28 09:48 多力宇扬 阅读(536) | 评论 (0)编辑 收藏

JDBC 2.0比1.0有了一些不同,体现在四个比较明显的方面:
1>. ResutlSet对象中的Cursor能够自由上下移动
2>. 能直接使用Java程序语言来更新DB表里的内容,而不需要额外写SQL语法
3>. 可以一次传送许多SQL语句到DB执行----Batch
4>. 新增2个数据类型(BLOB和CLOB)
   我们知道在JDBC 1.0时,只要用 connection.createStatement()就能取得Statement()对象.不过在2.0中多的createStatement()
多了两个参数值,需要我们自己来定义它.
public Statement createStatement(int resultSetType,
                                 int resultSetConcurrency)throws SQLException
   第一个参数resultSetType用来设定ResultSet对象中的光标是否可以自由上下移动,它的值有三种,TYPE_FORWARD_ONLY,TYPE_SCROLL_SENSITIVE,
TYPE_SCROLL_INSENSITIVE.若为TYPE_FORWARD_ONLY就表示和1.0一样只能用next()方法;然后后两者可以让Cursor随便的自由移动,不过,
它们两者最大的区别在于:当ResutlSet中的值有改变时,TYPE_SCROLL_SENSITIVE能取得修改后的值,而TYPE_SCROLL_INSENSITIVE则不能.
  第而个参数resultSetConcurrentcy,主要是设定ResultSet对象是只读(read-only)还是可以改变的(updateable),它可能的值有两种,
CONCUR_READ_ONLY或者是CONCUR_UPDATE.若设置为CONCUR_READ_ONLY,ResultSet对象和1.0一样;若为CONCUR_UPDATEABLE,那么就可以用
ResultSet对象执行数据库的修改,增加和移除功能.for example:
先看功能和1.0一样的写法:
Statement stmt=con.createStatement(ResultSet.TYPE_FORWARD_ONLY,
                                   ResultSet.CONCUR_READ_ONLY);
RestultSet rs=stmt.executeQuery("select ename,empno from emp");
while(rs.next())
{
   String name=rs.getString("ename");
   int empno=rs.getInt("empno");
   System.out.println("name="+name+","+"number="+empno);
}
输出结果为:
name=feiyang,number=1190
name=jack,   number=1230
name=BillGates number=12
...........
再看看下面这个:
Statement stmt=con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
                                   ResultSet.CONCUR_READ_ONLY);
RestultSet rs=stmt.executeQuery("select ename,empno from emp");
rs.afterLast();
while(rs.previous())
{
   String name=rs.getString("ename");
   int empno=rs.getInt("empno");
   System.out.println("name="+name+","+"number="+empno);
}
输出结果为:
name=BillGates number=12
name=jack,   number=1230
name=feiyang,number=1190
.............
这和上面第一有点不同的是顺序颠倒了,这是因为我们使用了rs.afterLast()这个方法.其实2.0中还有很多方法,如下:
rs.absolute(-1); //表示cursor在最后一笔数据,即 rs.last()
rs.absolute(1);  //表示cursor在第一笔数据,即rs.first()
rs.absolute(n);  //表示cursor在第N笔数据
假使我们目前有1000笔数据,取得第997笔
rs.absolute(-4);
还有一个方法和absolute很相像,那就是relative(),
rs.absolute(5); //表示第五笔数据
......
rs.relative(-3);  //表示cursor目前在第二笔数据
.......
rs.relative(1);  //cursor目前在第三笔数据
看看怎么用ResultSet对象执行更新数据库动作
   要让ResultSet对象执行更新数据库的动作,首先在声明Statement对象时,参数必须设置为TYPE_SCROLL_SENSITIVE和
CUNCOR_UPDATEABLE.
Statement stmt=con.createStatment(RestultSet.TYPE_SCROLL_SENSITIVE,
                                  ResultSet.CONCUR_UPDATEABLE);
ResultSet rs=stmt.executeQuery("select ename,empno from emp);
rs.last();
rs.updateInt("empno",2230);
rs.cancelRowUpdates();
rs.updateInt("empno",1213);
rs.updateRow();
新增数据到数据库
Statement stmt=con.createStatment(RestultSet.TYPE_SCROLL_SENSITIVE,
                                  ResultSet.CONCUR_UPDATEABLE);
ResultSet rs=stmt.executeQuery("select * from emp);
rs.moveToInsertRow();
rs.updateInt("empno",2230);
rs.updateString("ename","feiyang");
rs.updateString("job","clerk");
rs.updateFloat("sal",123456.5);
rs.insertRow();
删除数据
Statement stmt=con.createStatment(RestultSet.TYPE_SCROLL_SENSITIVE,
                                  ResultSet.CONCUR_UPDATEABLE);
ResultSet rs=stmt.executeQuery("select * from emp);
rs.absolute(4);
rs.deleteRow();
依次执行多条SQL语句
Statement stmt=con.createStatment();
int[] rows;
stmt.addBatch("insert into emp values('feiyang','123456')");
stmt.addBatch("insert into offcie values('employee','Shanghai')");
rows=stmt.executeBatch();
当执行大量数据的时候为了数据的完整性,建议使用Transaction
eg:
con.setAutoCommit(false);
Statement stmt=con.createStatement();
int[] rows;
stmt.addBatch("1...........");
stmt.addBatch("2...........");
stmt.addBatch("3...........");
stmt.addBatch("4...........");
stmt.addBatch("5...........");
stmt.addBatch("6...........");
rows=stmt.executeBatch();
con.commit();
在JDBC2.0中新增加BLOB和CLOB两个数据类型
BOLB指的是二进制大型对象(Binary Large Object),CLOB指的是字符大型对象(Character Large Object).它们用来处理大型
的数据类型,他们分别代表大量的二进制数据和文字数据.

posted @ 2006-06-28 09:46 多力宇扬 阅读(415) | 评论 (0)编辑 收藏

checkbox全选实现
 
function CheckOthers(form)
{
    for (var i=0;i<form.elements.length;i++)
    {
        var e = form.elements[i];
//        if (e.name != 'chkall')
            if (e.checked==false)
            {
                e.checked = true;// form.chkall.checked;
            }
            else
            {
                e.checked = false;
            }
    }
}

function CheckAll(form)
{
    for (var i=0;i<form.elements.length;i++)
    {
        var e = form.elements[i];
//        if (e.name != 'chkall')
            e.checked = true// form.chkall.checked;
    }
}
建立表单对象,表单名:name=form,并建立checkbox,命名:name="checked"
建立全选按钮,代码:
<INPUT title=选择所有的Banner,点击选定按钮 onclick=CheckAll(this.form) type=button value=全选 name=chkall style="cursor:hand">
建立反选按钮,代码:
<INPUT title=反向选择所有的Banner,点击选定按钮 onclick=CheckOthers(this.form) type=button value=反选 name=chkOthers style="cursor:hand">

 

 

完整代码:

<%@page contentType="text/html;charset=gb2312"%>
<html>
 <head>
  <title>Dory.Doo-测试JSTL</title>
  <script language="javascript">
   <!--
   function CheckOthers(form)
{
    for (var i=0;i<form.elements.length;i++)
    {
        var e = form.elements[i];
//        if (e.name != 'chkall')
            if (e.checked==false)
            {
                e.checked = true;// form.chkall.checked;
            }
            else
            {
                e.checked = false;
            }
    }
}

function CheckAll(form)
{
    for (var i=0;i<form.elements.length;i++)
    {
        var e = form.elements[i];
//        if (e.name != 'chkall')
            e.checked = true// form.chkall.checked;
    }
}
   -->
  </script>
 </head>
 <body>
  <h2>体育运动种类</h2>
  <hr>
  <form action="test.jsp" method="post" name="form">
   <input type="checkbox" name="sports" value="football"/>足球<br>
   <input type="checkbox" name="sports" value="basketball"/>蓝球<br>
   <input type="checkbox" name="sports" value="f1"/>F1<br>
   <input type="checkbox" name="sports" value="f3"/>赛车<br>
   <input type="checkbox" name="sports" value="f5"/>谈话<br>
   <input type="checkbox" name="sports" value="qe"/>好<br>
   <input type="checkbox" name="sports" value="fs"/>Helo<br>
   <input type="checkbox" name="sports" value="a1"/>a1<br>
   <input type="checkbox" name="sports" value="a2"/>a2<br>
   <input type="checkbox" name="sports" value="a3"/>a3<br>
   <input type="checkbox" name="sports" value="a4"/>a4<br>
   <input type="checkbox" name="sports" value="a5"/>a5<br>
   <input type="checkbox" name="sports" value="a6"/>a6<br>
   <input type="checkbox" name="sports" value="a7"/>a7<br>
   <br>
   <p></p>
   <input type="submit" name="submit" value="提交">
   <input type="reset" name="reset" value="重置">
  
<INPUT title="选择所有的Banner,点击选定按钮" onclick="CheckAll(this.form)"
 type="button" value="全选" name="chkall" style="cursor:hand">
   
<INPUT title="反向选择所有的Banner,点击选定按钮" onclick="CheckOthers(this.form)"
type="button" value="反选" name="chkOthers" style="cursor:hand">
  </form>
 </body>
</html>
 

posted @ 2006-06-28 09:37 多力宇扬 阅读(514) | 评论 (0)编辑 收藏

    File类

 一个File类的对象,表示了磁盘上的文件或目录。
 File类提供了与平台无关的方法来对磁盘上的文件或目录进行操作。

import java.io.*;
class FileTest
{
 public static void main(String[] args) throws Exception
 {
  //File f = new File("1.txt");
  //f.createNewFile();   创建文件
  //f.mkdir(); 创建文件夹
  //File f = new File("F:\\Java Develop\\1.txt");//使用绝对路径
  //f.createNewFile();
  /*
  *WINDOWS平台下有盘符,LINUX下是没有的
  *考虑到JAVA语言的平台性,所有用分隔符seperator/seperatorChar
  */
  /*
  File fDir = new File(File.separator);//创建了当前的根目录
  String strFile = "Java Develop"+File.separator+"1.txt";
  File f = new File(fDir,strFile);
  f.createNewFile();
  //f.delete();
  f.deleteOnExit();
  Thread.sleep(3000);
  */
  /*
  for(int i=0;i<5;i++)
  {
   File.createTempFile("linshi",".tmp");
   f.deleteOnExit();
  }
  Thread.sleep(3000);
  */
 
  File fDir = new File(File.separator);
  String strFile ="Java Develop"+File.separator;
  File f = new File(fDir,strFile);
  //文件过滤器
  String[] names = f.list(new FilenameFilter()
  {
   public boolean accept(File dir,String name)
   {
    return name.indexOf(".java")!=-1;
   }
  });
  for(int i=0;i<names.length;i++)
  {
   System.out.println(names[i]);
  }
 }
}

            流式I/0

 流(Stream)是字节的源或目的。
 两种基本的流是: 输入流(Input Stream)和输出流(Output Stream)。从从中读出一系列字节的
 对象称为输入流。而能向其中写入一系列字节的对象称为输出流。


           流的分类
 
 节点流: 从特定的地方读写的流类,例如:磁盘或一块内存区域。
 过滤流: 使用节点作为输入或输出。过滤流使用的是一个已经存在的输入流或输出流连接创建的。
 (如下图)

 InputStream(一个抽象的基类)
 .三个基本的读写方法
  abstract int read(): 读取一个字节数据,并返回到数据,如果返回-1,表示读到了输入流的
                       末尾。
  int read(byte[] b):  将数据读入一个字节数组,同时返回实际读取的字节数。如果返回-1,
                       表示读到了输入流的末尾。
  int read(byte[] b,int off,int len): 将数据读入一个字节数组,同时返回是实际读取的字
                       节数。如果返回-1,表示读到了输入流的末尾。off指定在数组b中存放
                       数据的起始偏移位置;len指定读取的最大字节数。
 其他的方法
  long-skip(long n): 在输入流中跳过n个字节,并返回实际跳过的字节数。
  int available():   返回在不发生阻塞的情况下,可读取的字节数。
  void close():      关闭输入流,释放和这个流相关的系统资源。
  void mark(int reqdlimit): 在输入流的当前位置放置一个标记,如果读取的字节数多余
                     readlimit设置的值,则流忽略这个标记。
  void reset():      返回到上一个标记。
  boolean markSupported(): 测试当前是否支持mark和reset方法。如果支持返回true,反之false。

         java.io包中的InputStream的类层次 (下图)

OutputStream

 三个基本的写方法
 abstract void write(int b): 往输出流中写入一个字节
 void write(byte[] b):       往输出流中写入数组b中的所有字节
 void writte(byte[] b,int off,int len): 往输出流中写入数组b中从偏移量off开始的len个
                             字节的数据
 其它方法
 void flush(): 刷新输出流,强制缓冲区中的输出字节被写出
 void close(): 关闭输出流,释放和这个流相关的系统资源

        java.io包中OutputStream的类层次(如下图)

基本的流类

 FileInputStream和FileOutputStream
 节点流,用于从文件中读取或往文件中写入字节流。如果在构造FileOutputStream时,文件已经
 存在,则覆盖这个文件。
 
 BufferedInputStream和BufferedOutputStream
 过滤流,需要使用已经存在的节点流来构造,提供带缓冲的读写,提高了读写的效率。

 DataInputStream和DataOutputStream
 过滤流,需要使用已经存在的节点流来构造,提供了读写Java中的基本数据类型的功能。

 PipedInputStream和PipedOutputStream
 管道流,用于线程间的通信。一个线程的PipedInputStream对象从另一个线程的PipedOutputStream
 对象读取输入。要使管道流有用,必须同时构造管道输入流和管道输出流。

code:
import java.io.*;
class StreamTest
{
 public static void main(String[] args)throws Exception
 {
  /*
  int data;
  while((data=System.in.read())!=-1)  //从标准设备读取数据
  {
   System.out.write(data);//从标准设备输出数据
  }
  */
  //输出流写数据,只需要关闭尾端的流就可以了,因为fos连接到了bos
  FileOutputStream fos = new FileOutputStream("1.txt");
  //fos.write("http://www.google.cn".getBytes());
  //fos.close();
  BufferedOutputStream bos = new BufferedOutputStream(fos);
  //bos.write("http//www.baidu.com".getBytes());
  //bos.flush();
  //bos.close();
  DataOutputStream dos=new DataOutputStream(bos); //连接到了bos和fis
  byte b=3;
  int i=78;
  char ch='a';
  float f=4.5f;
  dos.writeByte(b);
  dos.writeInt(i);
  dos.writeChar(ch);
  dos.writeFloat(f);
  dos.close(); //必须调用flush()或者close()不然不会写入硬盘
 
  //输入流读数据
  FileInputStream fis=new FileInputStream("1.txt");
  BufferedInputStream bis = new BufferedInputStream(fis);
  //byte[] buf=new byte[100];
  //int len=fis.read(buf);
  //int len=bis.read(buf);
  //System.out.println(new String(buf,0,len));
  //fis.close();
  //bis.close();
  //注意读取的顺序要和写的顺序一样
  DataInputStream dis = new DataInputStream(bis);
  System.out.println(dis.readByte());
  System.out.println(dis.readInt());
  System.out.println(dis.readChar());
  System.out.println(dis.readFloat());
  dis.close(); 
 
 }
}


管道输入/输出流 code:
import java.io.*;
class PipedStreamTest
{
 public static void main(String[] args)
 {
  PipedOutputStream pos=new PipedOutputStream();
  PipedInputStream pis=new PipedInputStream();
  //连接
  try
  {
   pos.connect(pis);
   new Producer(pos).start();
   new Consumer(pis).start();
  }
  catch(Exception e)
  {
   e.printStackTrace();
  }
 }
}

class Producer extends Thread
{
 private PipedOutputStream pos;
 public Producer(PipedOutputStream pos)
 {
  this.pos=pos;
 }
 public void run()
 {
  try
  {
   pos.write("hello,welcome!".getBytes());
   pos.close();
  }
  catch(Exception e)
  {
   e.printStackTrace();
  }
 }
}

class Consumer extends Thread
{
 private PipedInputStream pis;
 Consumer(PipedInputStream pis)
 {
  this.pis=pis;
 }
 public void run()
 {
  try
  {
   byte[] buf=new byte[100];
   int len=pis.read(buf);
   System.out.println(new String(buf,0,len));
   pis.close();
  }
  catch(Exception e)
  {
   e.printStackTrace();
  }
 }
}

=================================================================================
              Java I/O库的设计原则

 Java的I/O库提供了一个称做链接的机制,可以将一个流与另一个流首尾相接,形成一个流管道的链接。
 这种机制实际上是一种被称做为Decorator(装饰)的设计模式的应用。
 
 通过流的链接,可以动态的增加流的功能,而这些功能的增加是通过组合一些流的基本功能而动
 态获取的。

 我们要获取一个I/O对象,往往需要产生多个I/O对象,这也是Java I/O库不大容易掌握的原因,
 但在I/O库中的Decorator模式的运用,给我们提供了实现上的灵活性。

 I/O流的链接图(如下)

  Reader和Writer

 Java程序语言使用Unicode来表示字符串和字符。
 Reader和Writer这两个抽象类主要用来读写字符流。

 java.io包中Reader的类层次(如下图)

 java.io包中Writer的类层次(如下图)


 code:
import java.io.*;
class StreamTest
{
 public static void main(String[] args)throws Exception
 {
  /*
  FileOutputStream fos = new FileOutputStream("1.txt");
  OutputStreamWriter osw = new OutputStreamWriter(fos);
  BufferedWriter bw = new BufferedWriter(osw);
 
  bw.write("http://www.yahoo.com.cn");
  bw.close();
 
  FileInputStream fis = new FileInputStream("1.txt");
  InputStreamReader isr = new InputStreamReader(fis);
  BufferedReader br = new BufferedReader(isr);
  System.out.println(br.readLine());
  br.close();
  */
  //InputStreamReader/OutputStreamWriter是一个中间过度类,连接字符和字符串
  InputStreamReader isr = new InputStreamReader(System.in);
  BufferedReader br = new BufferedReader(isr);
  String strLine;
  while((strLine=br.readLine())!=null)
  {
   System.out.println(strLine);
  }
  br.close();
 }
}

            字符集的编码

 ASCII(American Standard Code for Information Interchange,美国信息互换标准代码),是基
 于常用的英文字符的一套电脑编码系统。我们知道英文中经常使用的字符,数字符号被计算机
 处理时都是以二进制编码的形式出现(bit)二进制数对应。其最高位是0,相应的十进制数是0-127
 如,数字1,有一些制表符和其他符号组成。ASCII是现金最通用的单字节编码系统。

 GB2312: GB2312码是中华人民共和国国家汉字信息交换用编码,全称《信息交换用汉字编码字
 符集-基本集》。主要用于给每一个中文字符指定相应的数字,也就是进行编码。一个中文字符
 用两个字节的数字来表示,为了和ASCII码有所区别,将中文字符每一个字节的最高位置都用1
 来表示。

 GBK:为了对更多的字符进行编码,国家又发布了新的编码系统GBK(GBK的K是“扩展”的汉语
 拼音的第一个字母)。在新的编码系统里,除了完全兼容GB2312外,还对繁体中文,一些不常用
 的汉字和许多符号进行了编码。

 ISO-8859-1:是西方国家所使用的字符编码集,是一种单字节的字符集,而英文实际上只用了其
 中数字小于128的部分。

 Unicode: 这是一种通用的字符集,对所有语言的文字进行统一编码,对每一个字符都采用2个字节
 来表示,对于英文字符采取前面加“0”字节的策略实现等长兼容。如"a"的ASCII码为0x61,
 UNICODE就为0x00,0x61。

 UTF-8: Elight-bit UCS Transformation Format,(UCS,Universal Character Set,通用字符集,
 UCS是所有其他字符集标准的一个超集)。一个7位的ASCII码值,对应的UTF码是一个字节,如果
 字符是0x0000,或在0x0080与0x007f之间,对应的UTF码是两个字节,如果字符在0x0800与0xffff
 之间,对应的UTF码是三个字节。
 编码:将一个Unicode码转换为本地字符表示的过程为编码。
  解码:将一个字节转换为一个字符(用Unicode表示),这个过程叫解码。
        [简单的说去获取一个Unicode码就是解码]
 code:

import java.util.*;
import java.nio.charset.*;
class CharsetTest
{
 public static void main(String[] args)throws Exception
 {
  /*
  Map m=Charset.availableCharsets();
  Set names=m.keySet();
  Iterator it =names.iterator();
  while(it.hasNext())
  {
   System.out.println(it.next());
  }
  */
  Properties pps=System.getProperties();
  //pps.list(System.out);
  pps.put("file.encoding","ISO-8859-1");
  int data;
  byte[] buf=new byte[100];
  int i=0;
  while((data=System.in.read())!='q')
  {
   buf[i]=(byte)data;
   i++;
  }
  String str=new String(buf,0,i);
  //String strGBK=new String(str.getBytes("ISO-8859-1"),"GBK");
  //System.out.println(strGBK);
  System.out.println(str);
 }
}

 

     RandomAccessFile

  RandomAccessFile类同时实现了DataInput和DataOutput接口,提供了对文件随机存取的功能,
  利用这个类可以在文件的任何位置读取或写入数据。
  RandomAccessFile类提供了一个文件指针,用来标志要进行读写操作的下一位数据的位置。

 
 code:
import java.io.*;
class RandomFileTest
{
 public static void main(String[] args)throws Exception
 {
  Student s1 = new Student(1,"zhangsan",98.5);
  Student s2 = new Student(2,"lisi",90.5);
  Student s3 = new Student(3,"wangwu",78.5);
 
  RandomAccessFile rsf=new RandomAccessFile("student.txt","rw");  //存取模式rw
  s1.WriteStudent(rsf);
  s2.WriteStudent(rsf);
  s3.WriteStudent(rsf);
 
  Student s =new Student();
  rsf.seek(0); //把文件指针移到文件首
  for(long i=0;i<rsf.length();i=rsf.getFilePointer())
  {
   s.ReadStudent(rsf);
   System.out.println(s.num+":"+s.name+":"+s.score);
  }
  rsf.close();
 }
}

class Student
{
 int num;
 String name;
 double score;
 Student()
 {
 
 }
 Student(int num,String name,double score)
 {
  this.num=num;
  this.name=name;
  this.score=score;
 }
 public void WriteStudent(RandomAccessFile raf)throws Exception
 {
  raf.writeInt(num);
  raf.writeUTF(name);
  raf.writeDouble(score);
 }
 public void ReadStudent(RandomAccessFile raf)throws Exception
 {
  raf.readInt();
  raf.readUTF();
  raf.readDouble(); 
 }
}


           对象序列化

 .将对象转换为字节流保存起来,并在日后还原这个对象,这种机制叫做对象序列化。
 .将一个对象保存到永久存储设备上称为持续性。
 .一个对象要想能够实现序列化,必须实现Serializable接口或Externalizable接口。
 .当一个对象被序列化时,只保存对象的非静态成员变量,不能保存任何的成员变量和静态的
  成员变量。
 .如果一个对象的成员变量是一个对象,那么这个对象的数据成员也会被保存。
 .如果一个可序列化的对象包含对某个不可序列化的对象的引用,那么整个序列化操作将会失败,
  并且会抛出一个NotSerializableException。我们可以将这个引用标记为transient,那么对象
  仍然可以序列化。

 code:
import java.io.*;
class ObjectSerialTest
{
 public static void main(String[] args)throws Exception
 {
  Employee e1 = new Employee("zhangsan",20,2800.50);
  Employee e2 = new Employee("lisi",22,25000.50);
  Employee e3 = new Employee("wangwu",23,12800.50);
  Employee e4 = new Employee("blovesaga",22,3800.50);
 
  FileOutputStream fos=new FileOutputStream("employee.txt");
  ObjectOutputStream oos=new ObjectOutputStream(fos);
  oos.writeObject(e1);
  oos.writeObject(e2);
  oos.writeObject(e3);
  oos.writeObject(e4);
  oos.close();
 
  FileInputStream fis = new FileInputStream("employee.txt");
  ObjectInputStream ois =new ObjectInputStream(fis);
  Employee e;
  for(int i=0;i<4;i++)
  {
   e=(Employee)ois.readObject();
   System.out.println(e.name+":"+e.age+":"+e.salary);
  }
  ois.close();
 }
}

class Employee implements Serializable
{
 String name;
 int age;
 double salary;
 transient Thread t1 =new Thread();
 Employee(String name,int age,double salary)
 {
  this.name=name;
  this.age=age;
  this.salary=salary;
 }
 //可以写private void readObject()方法来控制我们自己想要实现的
 private void writeObject(java.io.ObjectOutputStream oos)throws Exception
 {
  //例如我们自己写想要显示的顺序和那些需要显示
  oos.writeInt(age);
  oos.writeUTF(name);
  System.out.println("Write Object");
 }
 private void readObject(java.io.ObjectInputStream ois)throws Exception
 {
  //按照写入的顺序来读取
  age=ois.readInt();
  name=ois.readUTF();
  System.out.println("Read Object");
 }
}

posted @ 2006-06-27 17:40 多力宇扬 阅读(818) | 评论 (0)编辑 收藏

 Collection             Map(和Collection接口没任何关系)
       / \                         |
      /   \                        |      
 Set   List              SortedMap
    /
   /
SortedSet
(接口图)

所谓框架就是一个类库的集合。集合框架就是一个用来表示和操作集合的统一框架,包含了实现
集合的接口和类。
 
 集合框架中的接口

 .Collection: 集合层次中的根接口,JDK没有提供这个接口直接的实现类。
 .Set: 不能包含重复的元素。SortedSet是一个按照升序排列元素的Set。
 .List: 是一个有序的集合,可以包含重复的元素。提供了按照索引访问的方式。
 .Map: 包含了key-value对。Map不能包含重复的key。SortedMap是一个按照升序排列key的Map。
 
 集合框架中的实现类
 
 实线表示继承类,虚线表示实现类。
 (图如下)

.ArrayList: 我们可以将其看做是能够自动增长容量的数组。
 .利用ArrayList的toArray()返回一个数组。
 .Arrays.asList()返回一个列表。
 .迭代器(Iterator)给我们提供了一种通用的方式来访问集合中的元素。

 注意: 从集合类中获取一个数组 toArray(),从数组获取列表利用Arrays.asList()
 例子:
import java.util.*;
class ArrayListTest
{
 public static void printElement(Collection c)
 {
  Iterator it = c.iterator();
  while(it.hasNext())
  {
   System.out.println(it.next());
  }
 }
 public static void main(String[] args)
 {
  ArrayList a = new ArrayList();
  /*
  a.add("abc");
  a.add("def");
  a.add("hjk");
  */
 
  a.add(new Point(1,1));
  a.add(new Point(2,2));
  a.add(new Point(3,3));
  /*
  Object[] o;
  o=a.toArray();  //将集合类转换为数组
  for(int i=0;i<o.length;i++)
  {
   System.out.println(o[i]);
  }
 
  List b = new ArrayList();
  b=Arrays.asList(o);
  System.out.println(b);
 
  for(int i=0;i<a.size();i++)
  {
   System.out.println(a.get(i));
  }
 
  System.out.println(a);
  System.out.println(a);
  */
 
  /*
  Iterator it = a.iterator();
   如果要删除元素,必须先调用next方法
  it.next();
  it.remove();
  while(it.hasNext())
  {
   System.out.println(it.next());
  }
  */
  //迭代器的作用: 提供一组通用的访问方式
  printElement(a);
 }
}

class Point
{
 int x, y;
 Point(int x, int y)
 {
  this.x=x;
  this.y=y;
 }
 public String toString()
 {
  return "x="+x+","+"y="+y;
 }
}

 Collections类

 .排序: Collections.sort(); [区别与Arrays.sort()]
  (1) 自然排序(natural ordering);
  (2) 实现比较器(Comparator)接口。
 .取最大和最小的元素: Collections.max(),Collections.min();
 .在已排序的List中搜索指定的元素: Collections.binarySearch()。

 代码示例:
import java.util.*;
class ArrayListTest
{
 public static void printElement(Collection c)
 {
  Iterator it = c.iterator();
  while(it.hasNext())
  {
   System.out.println(it.next());
  }
 }
 public static void main(String[] args)
 {
  /*
  ArrayList a = new ArrayList();
 
  a.add("abc");
  a.add("def");
  a.add("hjk");
 
 
  a.add(new Point(1,1));
  a.add(new Point(2,2));
  a.add(new Point(3,3));
 
  Object[] o;
  o=a.toArray();  //将集合类转换为数组
  for(int i=0;i<o.length;i++)
  {
   System.out.println(o[i]);
  }
 
  List b = new ArrayList();
  b=Arrays.asList(o);
  System.out.println(b);
 
  for(int i=0;i<a.size();i++)
  {
   System.out.println(a.get(i));
  }
 
  System.out.println(a);
  System.out.println(a);
  */
 
  /*
  Iterator it = a.iterator();
   如果要删除元素,必须先调用next方法
  it.next();
  it.remove();
  while(it.hasNext())
  {
   System.out.println(it.next());
  }
  */
  //迭代器的作用: 提供一组通用的访问方式
  //printElement(a);
 
  Student s1 = new Student(1,"zhangsan");
  Student s2 = new Student(2,"lisi");
  Student s3 = new Student(3,"wangwu");
  Student s4 = new Student(3,"blovesaga");
 
  ArrayList a = new ArrayList();
  a.add(s1);
  a.add(s2);
  a.add(s3);
  a.add(s4);
 
  //Collections.sort(a);
  Collections.sort(a,new Student.StudentComparator());
  printElement(a);
 }
}

class Point
{
 int x, y;
 Point(int x, int y)
 {
  this.x=x;
  this.y=y;
 }
 public String toString()
 {
  return "x="+x+","+"y="+y;
 }
}

class Student implements Comparable
{
 int num;
 String name;
 //实现比较器,它总是和我们的一个类相关,用内部类
 static class StudentComparator implements Comparator  //为了调用方便声明为静态的
 {
  public int compare(Object o1,Object o2)
  {
   Student s1 = (Student)o1;
   Student s2 = (Student)o2;
   int result=s1.num > s2.num ? 1: (s1.num==s2.num ? 0 : -1);
   if(result==0)
   {
    return s1.name.compareTo(s2.name);
   }
   return result;
  }
 }
 Student(int num,String name)
 {
  this.num=num;
  this.name=name;
 }
 public int compareTo(Object o)
 {
  Student s=(Student)o;
  return num > s.num ? 1 :( (num==s.num) ? 0 : -1);
 }
 
 public String toString()
 {
  return +num+":"+name;
 }
}

posted @ 2006-06-27 17:36 多力宇扬 阅读(230) | 评论 (0)编辑 收藏

>>>>>>>>>>>>>>>>Runtime和Process类<<<<<<<<<<<<<<<<<<<
1> 每一个Java程序都有一个Runtime类的单一实例。
2> 通过Runtime.getRuntime()获取Runtime类的实例。
3> Runtime类是使用单例模式的一个例子。
   Runtime没有public的构造方法。我们必须用Runtime的静态方法getRuntime();我们可以用
   Runtime的exec来执行一个外部程序,也可以用来编译一个源文件(用来做图形界面的编译器)。
import java.io.*;
class RuntimeTest
{
 public static void main(String[] args)
 {
  Runtime rt=Runtime.getRuntime();
  //System.out.println(rt.freeMemory());
  try
  {
   //rt.exec("notepad");
   Process p=rt.exec("java ArrayTest");
   InputStream is=p.getInputStream(); //从执行ArrayTest类所得来的
   int data;
   while((data=is.read())!=-1)
   {
    System.out.print((char)data);
   }
  }
  catch(Exception e)
  {
   e.printStackTrace();
  }
 }
}

------------->>设计模式<<-------------
1> 在我们进行程序设计时,逐渐形成了一些典型问题和问题解决方案,这就是软件模式。
2> 每一个模式描述了一个在我们程序设计中经常发生的问题,以及该问题的解决方案。
3> 当我们碰到模式所描述的问题,就可以直接用相应的解决方法去解决这个问题,这就是设计模式。
<$>单例(Singleton)模式
1> 一个类只有一个实例,而且自行实例化并像整个系统提供这个实例,这个类称为单例类。
2> 单例类的一个重要特点就是类的构造方法是私有的,从而避免了外部用利用构造方法直接创建多个实例。
   如:Runtime类。

单例类的实现:(code)
class Singleton
{
 private static final Singleton st=new Singleton();
 private Singleton()
 {
 
 }
 public static Singleton getInstance()
 {
  return st;
 }
}

posted @ 2006-06-27 17:30 多力宇扬 阅读(650) | 评论 (0)编辑 收藏

=============================封装类===============
针对八种基本数据类型定义的相应的引用类型-封装类(包装类,包裹类)
基本数据类型          封装类
 boolean               Boolean
 byte                  Byte
 short                 Short
 int                   Integer
 long                  Long
 char                  Character
 float                 Float
 double                Double
所有的封状类都是一个只读类(不能修改的).针对没个基本类型我们只能建立一个这读的。

class Test
{
 public static void main(String[] args)
 {
  int i=3;
  Integer in=new Integer(i);
  int j=in.intValue();
  System.out.println(j);
  String str=in.toString();  //把Integer对象转换为String类型
  System.out.println("str="+str);
 
  String str1="123";
  System.out.println(Integer.valueOf(str1));  //把String类型转换为Integer类型
 
  boolean b1=false;
  Boolean b=new Boolean(b1);
  String s1=b.toString();
  System.out.println(s1);
 
  String s2="NO";
  System.out.println(Boolean.valueOf(s2));
 }
}

*****************Class*********************
1> 在Java中,每个class都有一个相应的Class对象。也就是说,当我们编写一个类,编译完成后,在生成
   的.class文件中,就会产生一个Class对象,用于表示这个类的类型信息。
2> 获取Class实例的方法有三种:
   <1>利用对象调用getClass()方法获得该对象的Class实例。
   <2>使用Class类的静态方法forName(),用类的名字获取一个Class的是实例。
   <3>运用.class的方式来获取Class实例,对于基本数据类型的封装类,还可以用.TYPE来获取相应的
      基本数据类型的Class实例。
   <4>在运行期间,如果我们要产生某个类的对象,JAVA虚拟机(JVM)会检查该类型的Class对象是否被
      加载,如果没有加载,JVM会根据类的名称找到.class文件并加载它。一旦某个类型的Class对象已
      经被加载到内存,就可以用它来产生该类型所有的对象。
   <5>newInstance()调用类中缺省的构造方法。(好处是我们在不知道类的名字的情况下去创造一个实例)
import java.lang.reflect.*;       //子包必须手动导入
class ClassTest
{
 public static void main(String[] args)//throws Exception
 {
  /*
  Point pt=new Point();             
  Class c1=pt.getClass();//利用对象调用getClass()方法获得该对象的Class实例
  System.out.println(c1.getName());
 
  Class c2=Class.forName("Point");//使用Class类的静态方法forName(),用类的名字获取一个Class的是实例
  System.out.println(c2.getName());
 
  Class c3=Point.class;//运用.class的方式来获取Class实例
  System.out.println(c3.getName());
 
  Class c4=Integer.TYPE;//封装类用.TYPE来获取相应的基本数据类型的Class实例。
  System.out.println(c4.getName());
  */
  /*
  System.out.println("before new Point()");
  new Point();
  System.out.println("after new Point()");
  Class.forName("Line");
  */
  /*
  if(args.length!=1)
  {
   return;
  }
  try
  {
   Class c=Class.forName(args[0]);
   Point pt=(Point)c.newInstance();
   pt.output();
  }
  catch(Exception e)
  {
   e.printStackTrace();
  }
  */
  if(args.length!=1)
  {
   return;
  }
  try
  {
   Class c=Class.forName(args[0]);
   Constructor[] cons=c.getDeclaredConstructors();
   /*
   for(int i=0;i<cons.length;i++)
   {
    System.out.println(cons[i]);
   }
   Method[] ms=c.getDeclaredMethods();
   for(int i=0;i<ms.length;i++)
   {
    System.out.println(ms[i]);
   }*/
   Class[] params=cons[0].getParameterTypes();
   Object[] paramValues=new Object[params.length];
   for(int i=0;i<params.length;i++)
   {
    if(params[i].isPrimitive())
    {
     paramValues[i]=new Integer(i+3);
    }
   }
   Object o=cons[0].newInstance(paramValues);
   Method[] ms=c.getDeclaredMethods();
   ms[0].invoke(o,null);
  }
  catch(Exception e)
  {
   e.printStackTrace();
  }
 
 }
}

class Point
{
 static
 {
  System.out.println("Loading Point");
 }
 int x,y;
 void output()
 {
  System.out.println("x="+x+","+"y="+y);
 }
 Point(int x,int y)
 {
  this.x=x;
  this.y=y;
 }
}

class Line
{
 static
 {
  System.out.println("Loading Line");
 }
}

posted @ 2006-06-27 17:29 多力宇扬 阅读(351) | 评论 (0)编辑 收藏

~~~~~~~~~~~~~~~~~~~~~~~~~~函数的调用~~~~~~~~~~~~~~~~~~~~
1> 在java中,传参时,都是以传值的形式惊行。
2> 对于基本数据类型,传递的是数据的拷贝,对于引用类型,传递的引用的拷贝。
3> 当我们在打印一个对象的时候,比如System.out.println(pt);,它会自动调用类的toString()方法
   ,所以建议在所有的子类中重写toString()方法。
我们写一个函数用来交换两个变量(x,y)的值.
 code:
class StringTest
{
 public static void change(int x, int y)
 {
  x=x+y;
  y=x-y;
  x=x-y;
 }
 /*
 public static void change(int[] num)
 {
  num[0]=num[0]+num[1];
  num[1]=num[0]-num[1];
  num[0]=num[0]-num[1];
 }
 public static void change(Point pt)
 {
  pt.x=pt.x+pt.y;
  pt.y=pt.x-pt.y;
  pt.x=pt.x-pt.y;
 }
 */
 public static void main(String[] args)
 {
 int x=3;
 int y=4;
 change(3,4);
 System.out.println("x="+x+","+"y="+y);
 }
我们期望的输出结果是 x=4,y=3 然后你运行后发现结果为x=3,y=4,并没有达到我们的要求,为什么呢?那是因为对于基本数据类型,传递的是数据的拷贝,对于引用类型,传递的是引用(首地址)的拷贝。看看下面的内存图解应该你就能看出来了.看看引用类型怎么来实现:

code:
class StringTest
{
 /*
 public static void change(int x, int y)
 {
  x=x+y;
  y=x-y;
  x=x-y;
 }
 */
 public static void change(int[] num)
 {
  num[0]=num[0]+num[1];
  num[1]=num[0]-num[1];
  num[0]=num[0]-num[1];
 }
 public static void change(Point pt)
 {
  pt.x=pt.x+pt.y;
  pt.y=pt.x-pt.y;
  pt.x=pt.x-pt.y;
 }
 public static void main(String[] args)
 {
  /*
   int x=3;
   int y=4;
   change(3,4);
   System.out.println("x="+x+","+"y="+y);
   */
   int[] num=new int[]{3,4};
   change(num);
   System.out.println("x="+num[0]+","+"y="+num[1]);
  
   Point pt=new Point();
   pt.x=3;
   pt.y=4;
   change(pt);
   System.out.println("x="+pt.x+","+"y="+pt.y); 
 }
class Point
{
 int x,y;
}
再看看引用类型的内存变化图:
以上说明了在Java中函数的调用:
a> 在Java中,传参时,都是以传值的方式进行。
b> 对于基本数据类型,传递的是数据的拷贝,对于引用类型,传递的是引用(首地址)的拷贝。

posted @ 2006-06-27 17:26 多力宇扬 阅读(228) | 评论 (0)编辑 收藏

^^^^^^^^^^^^^^^对象的克隆^^^^^^^^^^^^^
1> 为了获取对象的一份拷贝,我们可以利用Object类的clone()方法。
2> 在派生类中覆盖基类的clone(),并声明为public。
3> 在派生类的clone()方法中,调用super.clone()。
4> 在派生类中实现Cloneable接口。
4> 没有抽象方法的接口叫标识接口。
5> 为什么我们在派生类中覆盖Object的clone()方法时,一定要调用super.clone()呢?在运行时刻,Object 的clone()方法能识别出你要复制的是哪一个对象,然后为此对象分配空间,并进行对象的复制,将原 始对象的内容一一复制到新的对象空间去。

* 浅克隆是针对没有引用类型的变量来克隆。针对引用类型的克隆应该用Deeply Clone。
浅克隆:
Code:
class FleetClone
{
 public static void main(String[] args)
 {
   Professor p=new Professor("feiyang",23);
   Student s1=new Student("zhangshan",18,p);
   Student s2=(Student)s1.clone();
   s2.p.name="feifei";
   s2.p.age=30;
   System.out.println("name="+s1.p.name+","+"age="+s1.p.age);
 }
}
class Professor
{
 String name;
 int age;
 Professor(String name,int age)
 {
  this.name=name;
  this.age=age;
 }
}

class Student implements Cloneable
{
 Professor p;
 String name;
 int age;
 Student(String name, int age,Professor p)
 {
  this.name=name;
  this.age=age;
  this.p=p;
 }
 public Object clone()
 {
  Object o=null;
  try
  {
   o=super.clone();
  }
  catch(CloneNotSupportedException e)
  {
   e.printStackTrace();
  }
  return o;
 }
}
改变学生s2的教授信息,打印s1教授信息,结果为:name=feifei,age=30.产生这个结果是因为String是一个常量类型.
 
深克隆
code:
class DeeplyClone
{
 public static void main(String[] args)
 {
   Professor p=new Professor("feiyang",23);
   Student s1=new Student("zhangshan",18,p);
   Student s2=(Student)s1.clone();
   s2.p.name="Bill.Gates";
   s2.p.age=30;
   System.out.println("name="+s1.p.name+","+"age="+s1.p.age);
 }
}
class Professor implements Cloneable
{
 String name;
 int age;
 Professor(String name,int age)
 {
  this.name=name;
  this.age=age;
 }
 public Object clone()
 {
  Object o=null;
  try
  {
   o=super.clone();
  }
  catch(CloneNotSupportedException e)
  {
   e.printStackTrace();
  }
  return o;
 }
}

class Student implements Cloneable
{
 Professor p;
 String name;
 int age;
 Student(String name, int age,Professor p)
 {
  this.name=name;
  this.age=age;
  this.p=p;
 }
 public Object clone()
 {
  //Object o=null;
  Student o=null;
  try
  {
   o=(Student)super.clone();
  }
  catch(CloneNotSupportedException e)
  {
   e.printStackTrace();
  }
  o.p=(Professor)p.clone();
  return o;
 }
}
打印结果为:name=Bill.Gates,age=30,这就是深克隆.

posted @ 2006-06-27 17:24 多力宇扬 阅读(889) | 评论 (0)编辑 收藏

Java数组的相关操作

1> 在Java中所有的数组都有一个缺省的属性length,用于获取数组元素的个数。
2> 数组的复制: System.arraycopy()。
3> 数组的排序: Arrays.sort()。
4> 在已排序的数组中查找某个元素:Arrays.binarySearch()。
具体的看看下面的2个例子:
code1:
class ArrayTest
{
 public static void main(String[] args)
 {
  /*数组的copy
  int[] num1=new int[]{1,2,3};
  int[] num2=new int[3];
  System.arraycopy(num1,0,num2,0,num1.length);
  for(int i=0;i<num2.length;i++)
  {
   System.out.println(num2[i]);
  }
  */
  //引用类型的数组copy
  Point[] pts1=new Point[]{new Point(1,1),new Point(2,2),new Point(3,3)};
  Point[] pts2=new Point[3];
  System.arraycopy(pts1,0,pts2,0,pts1.length);
  for(int i=0;i<pts2.length;i++)
  {
   System.out.println("x="+pts2[i].x+","+"y="+pts2[i].y);
  }
  /*
  *因为引用类型传递的是引用的拷贝,所以我们修改pts2数组的第二个点的坐标,
  *当我们打印pts1数组的第一个点的坐标时,它的坐标点已经被修改为(5,5)了
  pts2[1].x=5;
  pts2[1].y=5;
  System.out.println("x="+pts1[1].x+","+"y="+pts1[1].y);
  */
 }
}

class Point
{
 int x, y;
 Point(int x,int y)
 {
  this.x=x;
  this.y=y;
 }
}


code2:
import java.util.*;
class TestArray
{
 public static void main(String[] args)
 {
  /*
  int[] num=new int[]{3,2,1};
  Arrays.sort(num);
  for(int i=0;i<num.length;i++)
  {
   System.out.println(num[i]);
  }
  int index=Arrays.binarySearch(num,3);
  System.out.println("index="+index);
  System.out.println("Element="+num[index]);
  */
  Student[] ss=new Student[]{new Student("zhangshan",1),
                            new Student("lisi",2),
                            new Student("wangwu",3),
                            new Student("mybole",3)};
   Arrays.sort(ss);
   for(int i=0;i<ss.length;i++)
   {
    System.out.println(ss[i]);
   }
   int index=Arrays.binarySearch(ss,new Student("lisi",2));
   System.out.println("name="+ss[index].name+","+"index="+index);
 }
}

class Student implements Comparable
{
 String name;
 int num;
 Student(String name,int num)
 {
  this.name=name;
  this.num=num;
 }
 public String toString()
 {
  return "name="+name+","+"number="+num;
 }
 public int compareTo(Object o)  //对于Object[]排序要求实现Comparable接口
 {
  Student s=(Student)o;
  //return num>s.num ? 1 :(num==s.num ? 0 : -1);
  int result=num>s.num ? 1 :(num==s.num ? 0 : -1);//按名字排序
  if(0==result)
  {
   result=name.compareTo(s.name);
  }
  return result;
 }
}

posted @ 2006-06-27 17:22 多力宇扬 阅读(170) | 评论 (0)编辑 收藏

理解继承是理解面向对象程序设计的关键.在Java中,通过关键字extends继承一个已有的类,被继承的类称为父类(超类,基类),新的类称为子类(派生类).在Java中不允许多继承.code:
class Animal
{
 int height,weight;
 void eat()
 {
  System.out.println("Animal eat!");
 }
 void sleep()
 {
  System.out.println("Animal sleep!");
 }
 void breathe()
 {
  System.out.println("Animal breathe!");
 }
}
class Fish extends Animal
{
 
}
class DoMain
{
 public static void main(String[] args)
 {
  Animal an=new Animal();
  Fish fn=new Fish();
 
  an.breathe();
  fn.breathe();
  fn.height=30;
  fn.weight=20;
 }
}
Result:
F:\Java Develop>javac Animal.java

F:\Java Develop>java DoMain
Animal breathe!
Animal breathe!
(这说明派生类继承了父类的所有方法和成员变量.)

方法的覆盖(override)
在子类中定义一个与父类同名,返回类型,参数类型均相同的一个方法,称为方法的覆盖,方法的覆盖发生在子类与父类之间.
code:
class Animal
{
 int height,weight;
 void eat()
 {
  System.out.println("Animal eat!");
 }
 void sleep()
 {
  System.out.println("Animal sleep!");
 }
 void breathe()
 {
  System.out.println("Animal breathe!");
 }
}
class Fish extends Animal
{
 int weight,height;   //隐藏了父类的weight,height;
 void breathe()  //override method breathe()
 {
  super.breathe();  //用super调用父类的构造方法
  System.out.println("Fish bubble");
 }
}
class DoMain
{
 public static void main(String[] args)
 {
 // Animal an=new Animal();
  Fish fn=new Fish();
 
  an.breathe();
  fn.breathe();
  fn.height=30;
  fn.weight=20;
 }
}
输出结果:
F:\Java Develop>javac Animal.java

F:\Java Develop>java DoMain
Animal breathe!
Fish bubble

特殊变量super
* 使用特殊变量super提供对父类的访问
* 可以使用super访问父类被子类隐藏的变量或覆盖的方法
* 每个子类构造方法的第一条语句都是隐含的调用super,如果父类没有这种形式的构造函数就会报错.
code:
class Animal
{
 int height,weight;
 Animal()
 {
  System.out.println("Animal construct");
 }
 void eat()
 {
  System.out.println("Animal eat!");
 }
 void sleep()
 {
  System.out.println("Animal sleep!");
 }
 void breathe()
 {
  System.out.println("Animal breathe!");
 }
}

class Fish extends Animal
{
 Fish()
 {
  System.out.println("Fish construct");
 }
 void breathe()  //override method breathe()
 {
  System.out.println("Fish bubble");
 }
}
class DoMain
{
 public static void main(String[] args)
 {
  //Animal an=new Animal();
  Fish fn=new Fish();
 
  //an.breathe();
  //fn.breathe();
  //fn.height=30;
  //fn.weight=20;
 }
}
输出结果:
F:\Java Develop>javac Animal.java

F:\Java Develop>java DoMain
Animal construct
Fish construct



 通过覆盖父类的方法来实现,在运行时根据传递对象的引用,来调用相应的方法.
code:
class Animal
{
 int height,weight;
 Animal()
 {
  System.out.println("Animal construct");
 }
 void eat()
 {
  System.out.println("Animal eat!");
 }
 void sleep()
 {
  System.out.println("Animal sleep!");
 }
 void breathe()
 {
  System.out.println("Animal breathe!");
 }
}

class Fish extends Animal
{
 Fish()
 {
  System.out.println("Fish construct");
 }
 void breathe()  //override method breathe()
 {
  System.out.println("Fish bubble");
 }
}
class DoMain
{
 static void fn(Animal an)
 {
  an.breathe();
 }
 public static void main(String[] args)
 {
  //Animal an=new Animal();
  Fish fh=new Fish();
  Animal an;
  an=fh;
  DoMain.fn(an);
 }
}

posted @ 2006-06-27 17:20 多力宇扬 阅读(197) | 评论 (0)编辑 收藏

从今天开始从零学习JAVA,希望可以认识到更多的朋友,可以让自己的JAVA之路走得更为顺利一些!买了几本书来看也听了几接课,觉得JAVA很吸引我,我想我可以走得更远的.自信是最重要的.
    OOP(Object Oriented Programming)描述的是对象与对象之间的相互作用.听老师将面向过程与面向对象的最大区别是: 过程化程序设计先确定算法,再确定数据结构,再确定运算.面向过程编程,习惯于先建立数据结构存放数据并定义方法(函数)来操作数据;而面向对象的则是构建一个模型,将数据与方法组织在一起.
    我们可以把现实世界的事物抽象为对象.对象一般都有两个特征:状态(Status),行为(Behavior).软件的对象概念是由显示世界对象抽象而来.把现实世界的状态保存软件对象的变量中;现实世界对象的行为通过软件对象的方法(函数)来实现.
    我们把相似的对象划分成一个类.在软件中类就是一个模板,它定义了通用于一个特定种类的所有对象的状态(变量)和行为(方法).类是创建对象的模板,对象是类的实例.
    面向对象编程的难点在于思路的转变.我们通常习惯与考虑解决问题的方法,而不是抽象成对象再去解决它.
 类的构造方法
* 构造方法的名字和类名相同,并且没有返回值.
* 构造方法主要用于定义类的初始化状态.
* 我们不能直接调用构造方法,必须通过new关键字来自动调用,从而创建类的实例.
* Java的类都要求有构造方法,如果没有定义构造方法,Java编译器会提供一个缺省的构造方法,也就是不参数的构造方法.
方法的重载(overload)
 重载构成的条件:方法的名称相同,但参数类型或参数个数不同,才能构成方法的重载.
code:
class Point
{
 int x,y;
 /*
  *带参数的构造方法和不带参数的构造方法就构成了方法(函数)的重载
 */
 Point(int a,int b)
 {
  x=a;
  y=b;
 }
 Point()
 {
 
 }
 void output()
 {
  System.out.println(x);
  System.out.println(y);
 }
 public static void main(String[] args)
 {
  //调用不带参数的构造方法
  //Point p=new Point();
  //pt.x=10;
  //pt.y=20;
  //p.output();
  Point p1=new Point(3,3); //调用带参数的构造方法
  p1.output();
 }
}
特殊变量this
* this变量代表对象本身
* 当类中有两个同名变量,一个属于类(类的成员变量),一个属于某个特定的方法(方法中的局部变量),使用this区分成员变量和局部变量.
* 使用this简化构造函数的调用
code:
class Point
{
 int x,y;
 /*
  *带参数的构造方法和不带参数的构造方法就构成了方法(函数)的重载
 */
 Point(int a,int b)
 {
  x=a;
  y=b;
 }
 Point()
 {
  this(1,1);
 }
 void output()
 {
  System.out.println(x);
  System.out.println(y);
 }
 /*output()方法定义的形参与成员变量同名了,
 *那么在output()里就看不到成员变量的x,y了,它被隐藏了.
 */
 void output(int x, int y)
 {
  this.x=x;
  this.y=y;
 }
 public static void main(String[] args)
 {
  Point pt=new Point(3,3);
  pt.output(5,5);
  pt.output();
 }
}
一个类所有的实例(对象)调用的成员方法在内存中只有一份拷贝,尽管在内存中可能有多个对象,而数据成员在内的没个对象中都存在着一份拷贝.this变量允许相同的实例方法为不同的对象工作.每当调用一个实例方法时,this变量被设置成引用该实例方法的特定的类的对象.方法的代码接着会与this所代表的对象的特定数据建立关联.

posted @ 2006-06-27 17:19 多力宇扬 阅读(289) | 评论 (0)编辑 收藏

JAVA 程序员面试 32 问

第一,谈谈 final , finally , finalize 的区别?

Final :修饰符(关键字)如果一个类被声明为 final ,意味着它不能再派生出新的子类,不能作为父类被继承。因此一个类不能既被声明为 abstract 的,又被声明为 final 的。将变 量或方法声明为 final ,可以保证它们在使用中不被改变。被声明为 final 的变量必须在声 明时给定初值,而在以后的引用中只能读取,不可修改。被声明为 final 的方法也同样只能 使用,不能重载 finally ?再异常处理时提供 finally{} 块来执行任何清除操作。如果抛出一个异常,那么 相匹配的 catch 子句就会执行,然后控制就会进入 finally 块(如果有的话)。 finalize :方法名。 Java 技术允许使用 finalize ()方法在垃圾收集器将对象从内存中
清除出去之前做必要的清理工作。这个方法是由垃圾收集器在确定这个对象没有被引用时 对这个对象调用的。它是在 Object 类中定义的,因此所有的类都继承了它。子类覆盖 fi nalize ()方法以整理系统资源或者执行其他清理工作。 finalize () 方法是在垃圾收集 器删除对象之前对这个对象调用的。
 

第二, Anonymous Inner Class (匿名内部类) 是否可以 extends (继承)其它类,是否 可以 implements (实现) interface (接口)?

匿名的内部类是没有名字的内部类。不能 extends (继承) 其它类,但一个内部类可以作 为一个接口,由另一个内部类实现。

第三, Static Nested Class 和 Inner Class 的不同,说得越多越好(面试题有的很笼统)?
 
Nested Class (一般是 C++ 的说法), Inner Class (一般是 JAVA 的说法)。 Java 内部类
与 C++ 嵌套类最大的不同就在于是否有指向外部的引用上。
具体可见 http : //www.frontfree.net/articles/services/view.asp ?id=704&page=1  注:静态内部类( Inner Class )意味着 1 创建一个 static 内部类的对象,不需要一个外部类对象,2 不能从一个 static 内部类的一个对象访问一个外部类对象。

第四, & 和 && 的区别?
 
& 是位运算符。 && 是布尔逻辑运算符。

第五, HashMap 和 Hashtable 的区别?
 
都属于 Map 接口的类,实现了将惟一键映射到特定的值上。 HashMap 类没有分类或者排序。它允许一个 null 键和多个 null 值。 Hashtable 类似于 HashMap ,但是不允许 null 键和 null 值。它也比 HashMap 慢,因为 它是同步的。

第六, Collection 和 Collections 的区别?

Collections 是个 java.util 下的类,它包含有各种有关集合操作的静态方法.Collection 是个 java.util 下的接口,它是各种集合结构的父接口。

第七,什么时候用 assert ?

断言是一个包含布尔表达式的语句,在执行这个语句时假定该表达式为 true 。如果表达式 计算为false ,那么系统会报告一个 AssertionError 。它用于调试目的:assert(a > 0); // throws an AssertionError if a <= 0 : 断言可以有两种形式:
assert Expression1 ;
assert Expression1 : Expression2 ;
Expression1 应该总是产生一个布尔值。
Expression2 可以是得出一个值的任意表达式。这个值用于生成显示更多调试信息的 Str ing 消息.断言在默认情况下是禁用的。要在编译时启用断言,需要使用 source 1.4 标记:
javac -source 1.4 Test.java
要在运行时启用断言,可使用 -enableassertions 或者 -ea 标记。
要在运行时选择禁用断言,可使用 -da 或者 -disableassertions 标记。
要系统类中启用断言,可使用 -esa 或者 -dsa 标记。还可以在包的基础上启用或者禁用 断言.可以在预计正常情况下不会到达的任何位置上放置断言。断言可以用于验证传递给私有方法的参数。不过,断言不应该用于验证传递给公有方法的参数,因为不管是否启用了断言 ,公有方法都必须检查其参数。不过,既可以在公有方法中,也可以在非公有方法中利用 断言测试后置条件。另外,断言不应该以任何方式改变程序的状态。

第八, GC 是什么 ? 为什么要有 GC? ( 基础 ) ?

GC 是垃圾收集器。 Java 程序员不用担心内存管理,因为垃圾收集器会自动进行管理。要请求垃圾收集,可以调用下面的方法之一:
System.gc() 
 Runtime.getRuntime().gc()

第九, String s = new String("xyz"); 创建了几个 String Object?
两个对象,一个是 “xyx”, 一个是指向 “xyx” 的引用对象 s 。

第十, Math.round(11.5) 等於多少 ? Math.round(-11.5) 等於多少 ?
Math.round(11.5) 返回( long ) 12 , Math.round(-11.5) 返回( long ) -11;

第十一, short s1 = 1; s1 = s1 + 1; 有什么错 ? short s1 = 1; s1 += 1; 有什么错 ?

short s1 = 1; s1 = s1 + 1; 有错, s1 是 short 型, s1+1 是 int 型 , 不能显式转化为 short 型.可修改为
s1 =(short)(s1 + 1) 。 short s1 = 1; s1 += 1 正确。

第十二, sleep() 和 wait() 有什么区别 ?
搞线程的最爱 sleep() 方法是使线程停止一段时间的方法。在 sleep 时间间隔期满后,线程不一定立即恢复执行。这是因为在那个时刻,其它线程可能正在运行而且没有被调度为放弃执行,除非 (a)“ 醒来 ” 的线程具有更高的优先级, (b) 正在运行的线程因为其它原因 而阻塞。wait() 是线程交互时,如果线程对一个同步对象 x 发出一个 wait() 调用,该线程会暂停执行,被调对象进入等待状态,直到被唤醒或等待时间到。

第十三, Java 有没有 goto?
Goto?java 中的保留字,现在没有在 java 中使用。

第十四,数组有没有 length() 这个方法 ? String 有没有 length() 这个方法?
数组没有 length() 这个方法,有 length 的属性。
String 有有 length() 这个方法。

第十五, Overload 和 Override 的区别。 Overloaded 的方法是否可以改变返回值的类型 ?

方法的重写 Overriding 和重载 Overloading 是 Java 多态性的不同表现。重写 Overriding 是父类与子类之间多态性的一种表现,重载 Overloading 是一个类中多态性的一种表现。如果在 子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写 (Overriding) 。子类的对象使用这个方法时,将调用子类中的定义,对它而言,父类中的定义如同被 “ 屏蔽” 了。如果在一个类中定义了多个同名的方法,它们或有不同的参数个数或有不同的参数 类型,则称为方法的重载 (Overloading) 。 Overloaded 的方法是可以改变返回值的类型。


第十六, Set 里的元素是不能重复的,那么用什么方法来区分重复与否呢 ? 是用 == 还是 equ
als()? 它们有何区别 ?
Set 里的元素是不能重复的,那么用 iterator() 方法来区分重复与否。 equals() 是判读两个Set 是否相等。
equals() 和 == 方法决定引用值是否指向同一对象 equals() 在类中被覆盖,为的是当两个分离的对象的内容和类型相配的话,返回真值。

第十七,给我一个你最常见到的 runtime exception ?
ArithmeticException, ArrayStoreException, BufferOverflowException,
BufferUnderflowException, CannotRedoException,
CannotUndoException, ClassCastException, CMMException,
ConcurrentModificationException,
DOMException, EmptyStackException, IllegalArgumentException,
IllegalMonitorStateException,
IllegalPathStateException, IllegalStateException,
ImagingOpException,
IndexOutOfBoundsException, MissingResourceException,
NegativeArraySizeException, NoSuchElementException,
NullPointerException, ProfileDataException, ProviderException,
RasterFormatException, SecurityException, SystemException,
UndeclaredThrowableException,
UnmodifiableSetException, UnsupportedOperationException

第十八, error 和 exception 有什么区别 ?
error 表示恢复不是不可能但很困难的情况下的一种严重问题。比如说内存溢出。不可能指望程序能处理这样的情况exception 表示一种设计或实现问题。也就是说,它表示如果程序运行正常,从不会发生的情况.

第十九, List, Set, Map 是否继承自 Collection 接口 ?
List , Set 是.Map 不是

第二十, abstract class 和 interface 有什么区别 ?

声明方法的存在而不去实现它的类被叫做抽象类( abstract class ),它用于要创建一个体现某些基本行为的类,并为该类声明方法,但不能在该类中实现该类的情况。不能创建abstract 类的实例。然而可以创建一个变量,其类型是一个抽象类,并让它指向具体子类的一个实例。不能有抽象构造函数或抽象静态方法。 Abstract 类的子类为它们父类中的所 有抽象方法提供实现,否则它们也是抽象类为。取而代之,在子类中实现该方法。知道其 行为的其它类可以在类中实现这些方法。
接口( interface )是抽象类的变体。在接口中,所有方法都是抽象的。多继承性可通过实 现这样的接口而获得。接口中的所有方法都是抽象的,没有一个有程序体。接口只可以定 义 static final 成员变量。接口的实现与子类相似,除了该实现类不能从接口定义中继承 行为。当类实现特殊接口时,它定义(即将程序体给予)所有这种接口的方法。然后,它可以在实现了该接口的类的任何对象上调用接口的方法。由于有抽象类,它允许使用接口名作为引用变量的类型。通常的动态联编将生效。引用可以转换到接口类型或从接口类型转换, instanceof 运算符可以用来决定某对象的类是否实现了接口。

第二十一, abstract 的 method 是否可同时是 static, 是否可同时是 native ,是否可同时是 s
ynchronized?
都不能

第二十二,接口是否可继承接口?抽象类是否可实现 (implements) 接口?抽象类是否可继承实体类 (concrete class)?

接口可以继承接口。抽象类可以实现 (implements) 接口,抽象类是否可继承实体类,但前提是实体类必须有明确的构造函数。

第二十三,启动一个线程是用 run() 还是 start()?
启动一个线程是调用 start() 方法,使线程所代表的虚拟处理机处于可运行状态,这意味着它可以由 JVM 调度并执行。这并不意味着线程就会立即运行。 run() 方法可以产生必须退出 的标志来停止一个线程。


第二十四,构造器 Constructor 是否可被 override?
构造器 Constructor 不能被继承,因此不能重写 Overriding ,但可以被重载 Overloading 。


第二十五,是否可以继承 String 类 ?
String 类是 final 类故不可以继承。

第二十六,当一个线程进入一个对象的一个synchronized 方法后,其它线程是否可进入此对象的其它方法?
不能,一个对象的一个 synchronized 方法只能由一个线程访问。

第二十七,try {} 里有一个 return 语句,那么紧跟在这个 try 后的 finally {} 里的 code 会不会被执行,什么时候被执行,在 return 前还是后 ?
会执行,在 return 前执行。

第二十八,编程题 : 用最有效率的方法算出 2 乘以 8 等於几 ?
有 C 背景的程序员特别喜欢问这种问题。
2 << 3

第二十九,两个对象值相同 (x.equals(y) == true) ,但却可有不同的 hash code ,这句话
对不对 ?
不对,有相同的 hash code 。

第三十,当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递 ? 是值传递。 Java 编程语言只由值传递参数。当一个对象实例作为一个参数被传递到方法中时,参数的值就是对该对象的引用。对象的内容可以在被调用的方法中改变,但对象的引用是永远不会改变的。

第三十一, swtich 是否能作用在 byte 上,是否能作用在 long 上,是否能作用在 String 上 ?

switch ( expr1 )中, expr1 是一个整数表达式。因此传递给 switch 和 case 语句的参数应该是 int 、 short 、 char 或者 byte 。 long,string 都不能作用于 swtich 。

第三十二,编程题 : 写一个 Singleton 出来?
Singleton 模式主要作用是保证在 Java 应用程序中,一个类 Class 只有一个实例存在。

一般 Singleton 模式通常有几种种形式 :
第一种形式 : 定义一个类,它的构造函数为 private 的,它有一个 static 的 private 的该类变量,在类初始化时实例话,通过一个 public 的 getInstance 方法获取对它的引用 , 继而调用其中的方法。
public class Singleton {
private Singleton(){}
// 在自己内部定义自己一个实例,是不是很奇怪?
// 注意这是 private 只供内部调用
private static Singleton instance = new Singleton();
// 这里提供了一个供外部访问本 class 的静态方法,可以直接访问
public static Singleton getInstance() {
   return instance;   
}
}

第二种形式 :

public class Singleton {
private static Singleton instance = null;
public static synchronized Singleton getInstance() {
// 这个方法比上面有所改进,不用每次都进行生成对象,只是第一次     
// 使用时生成实例,提高了效率!
if (instance==null)
   instance = new Singleton();
return instance;    }
}

其他形式 :
定义一个类,它的构造函数为 private 的,所有方法为 static 的。
一般认为第一种形式要更加安全些

第三十三 Hashtable 和 HashMap ?
Hashtable 继承自 Dictionary 类,而 HashMap 是 Java1.2 引进的 Map interface 的一个实现

HashMap 允许将 null 作为一个 entry 的 key 或者 value ,而 Hashtable 不允许还有就是, HashMap 把 Hashtable 的 contains 方法去掉了,改成 containsvalue 和 containsKey.因为contains 方法容易让人引起误解。

最大的不同是,Hashtable 的方法是Synchronize 的,而HashMap 不是,在多个线程访问 Hashtable 时,不需要自己为它的方法实现同步,而 HashMap 就必须为之提供外同步.Hashtable 和 HashMap 采用的 hash/rehash 算法都大概一样,所以性能不会有很大的差异。

posted @ 2006-06-27 17:15 多力宇扬 阅读(166) | 评论 (0)编辑 收藏

blovesaga在一家小超级市场购买一个1.10元棒棒糖,但是他的钱报中都是两块一张的钞票.如果他用一张两块的钞票买这个棒棒糖,那么应该找给他多少零钱呢?
     编写一个程序解决这个问题.
code:
class Change
{
 public static void main(String[] args)
 {
  System.out.println(2.00-1.10);
 }
}

       blovesage写下这段代码我们期望得到应该找回的零钞0.90,但是当运行后他发现数据不兑,运行结果为:0.8999999999999999,与预期的0.90不一样。为什么呢?搞了半天原因在于1.1这个数不能被精确的表示为一个double,因此被表示为最接近它的double值.该程序从2中减去这个值得.遗憾的是,这个结果打印出来并不是接近0.9的double值.这说明: 并不是所有的小数都可以用二进制浮点数精确表示.二进制浮点对于货币计算是非常不适合的.
      要解决这个问题有两个办法:一是使用某种整数类型,例如int或long,并且分单位来计算.如下:
System.out.println((200-110)+"fen");
结果为90分.二是使用执行小数运算的BigDecimal.它还可以通过JDBC与SQL DECIMAL类型进行互操作.这里需要注意的是: 一定要用BigDecimal(String)构造器,而千万不要用BigDecimal(double).后一个构造器将用它的参数值来创建一个实例.例如new BigDecimal(.1),它将返回一个BigDecimal,也即0.10000000000000000555111512312578270211815834041015625.正确使用我们就可以得到期望的结果0.90:
code:
import java.math.BigDecimal;
class Change
{
 public static void main(String[] args)
 {
  System.out.println(new BigDecimal("2.00").
                     subtract(new BigDecimal("1.10")));
 }
}
Print:
F:\Java Develop>java Change
0.90

posted @ 2006-06-27 17:03 多力宇扬 阅读(175) | 评论 (0)编辑 收藏

转型用于将一种类型转换到另一种类型.看看下面的code运行后你猜会打印什么?
 public class Multicast
{
 public static void main(String[] args)
 {
  System.out.println((int)(char)(byte)-1);
 }
}
 转,转,转,我给转晕了,从int数值-1开始,然后从int转换为byte,之后转为char,最后转型回int.第一个转型将数值从32为窄化到8位,第二个转型从8位拓宽为16位,最后从16位拓宽到32位.这个数值最终回到起点了吗?运行一看不就知道了吗?
Print:
F:\Java Develop>javac Multicast.java

F:\Java Develop>java Multicast
65535
啊,这么会是65535?
oh,my god!有条规则: 如果最初的数值类型是有符号的,那么就执行符号扩展;如果他是char,那么不管它将要被转换成什么类型,都执行另扩展.
   用这条规则来44看.因为byte是有符号的,所以在将byte数值-1转换成char时.会发生符号扩展.作为结果的char数值16位就都被置位了,因此它等于2^16-1(2的16次方减1),就是65535.从char到int的转型也是一个扩展,
用规则来说它将执行另扩展,而不是符号扩展.作为int的结果数值就是65535和打印的一样.
   从这个例子我们得到一个教训:如果通过观察不能确定程序将要做什么,那么它做的就很有可能不是你想要的.

posted @ 2006-06-27 17:02 多力宇扬 阅读(162) | 评论 (0)编辑 收藏

下面这个可怜的小程序并不能干脆的做决定。它的decisive方法将返回true。但是它也返回false。那么,它到底打印的是什么呢?甚至,合法吗?

class Indecisive
{
 public static void main(String[] args)
 {
  System.out.println(decisive());
 }
 static boolean decisive()
 {
  try
  {
   return true;
  }
  finally
  {
   return false;
  }
 }
}
   你可能认为这个程序不合法。毕竟,decisive方法不能同时返回true和false。如果你尝试一下,就会发现它
编译时没有任何错误,并且它打印的是false。为什么呢?
    原因在于就是在:在一个try-finally语句中,finally语句块总是在控制权离开try语句块时执行。无论try
语句块是正常结束的,还是意外结束,情况都是如此。在一条语句或一个语句块抛出一个异常,或者对某个封闭类型语句执行了一个break或continue,或是像这个程序一样执行了一个return时,将发生意外结束。之所以称为意外结束,是因为它们阻止程序按顺序执行下面的语句。
    当try语句块和finally语句块都意外结束时,在try语句块中引发意外结束的原因将被丢弃,而整个try-finally
语句意外结束的原因将与finally语句块意外结束的原因相同。在这个程序中,在try语句块中的return语句所
引发的意外结束将被丢弃,而try-finally语句意外结束是由finally语句块中的return造成的。简单的讲,程序
尝试着(try)返回(return)true,但是它最终(finally)返回(return)的是false。
    总之,每一个finally语句块都应该正常结束,除非抛出不受检查的异常。千万不要用return,break,continue或throw来退出finally语句块,并且千万不要允许让受检查的异常传播到finally语句块之外。

posted @ 2006-06-27 17:01 多力宇扬 阅读(185) | 评论 (0)编辑 收藏