ï»??xml version="1.0" encoding="utf-8" standalone="yes"?>人人超碰在线,久久久水蜜桃,中国动漫在线观看完整版免费http://www.aygfsteel.com/EricGu/专注 学习(f¨¤n) 实践 创新zh-cnMon, 04 Aug 2025 12:14:33 GMTMon, 04 Aug 2025 12:14:33 GMT60ora10ginstant ¾_„¡®€å®¢æˆ·ç«¯é‡åˆ?system.data.oracleclient 需è¦?oracle 客户端èÊYä»?.1.7 或更高版æœ?/title><link>http://www.aygfsteel.com/EricGu/archive/2012/04/19/375255.html</link><dc:creator>Eric Gu</dc:creator><author>Eric Gu</author><pubDate>Thu, 19 Apr 2012 05:09:00 GMT</pubDate><guid>http://www.aygfsteel.com/EricGu/archive/2012/04/19/375255.html</guid><wfw:comment>http://www.aygfsteel.com/EricGu/comments/375255.html</wfw:comment><comments>http://www.aygfsteel.com/EricGu/archive/2012/04/19/375255.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/EricGu/comments/commentRss/375255.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/EricGu/services/trackbacks/375255.html</trackback:ping><description><![CDATA[     遇到System.Data.OracleClient 需è¦?Oracle 客户端èÊYä»?8.1.7 或更高版本。一般第一反映都是ä¼?x¨¬)出处ç?nbsp; oracle_home æ–‡äšgå¤ÒŽ(gu¨©)ƒé™ã€‚可是有时时å€?不管你怎么摆弄权限åQŒæ€Žä¹ˆiisresetåQŒæ€Žä¹ˆé‡å¯ç”?sh¨´)脑都解决不了(ji¨£n),cmd  path 明明可以看到有oracle_home 路径啊。问题在于。环境变量中åQ?ora10gInstant ¾_„¡®€å®¢æˆ·ç«¯é»˜è®¤æŠŠå˜é‡æ·ÕdŠ åˆ?Administrator 的用户变量了(ji¨£n)åQŒæˆ‘们要做的是把  用户变量中的 Path å€?转到 ¾pȝ»Ÿå˜é‡ä¸­çš„ Path 中ã€?img src ="http://www.aygfsteel.com/EricGu/aggbug/375255.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/EricGu/" target="_blank">Eric Gu</a> 2012-04-19 13:09 <a href="http://www.aygfsteel.com/EricGu/archive/2012/04/19/375255.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用 spring 2.5 注释驱动çš?ioc 功能 http://www.aygfsteel.com/EricGu/archive/2010/12/15/340791.htmlEric GuEric GuWed, 15 Dec 2010 06:40:00 GMThttp://www.aygfsteel.com/EricGu/archive/2010/12/15/340791.htmlhttp://www.aygfsteel.com/EricGu/comments/340791.htmlhttp://www.aygfsteel.com/EricGu/archive/2010/12/15/340791.html#Feedback0http://www.aygfsteel.com/EricGu/comments/commentRss/340791.htmlhttp://www.aygfsteel.com/EricGu/services/trackbacks/340791.html

在项目中使用Spring的注解,关于spring的注解,ç”׃¸¤¿Uæ³¨è§£æ–¹å¼ï¼Œ

åŸÞZºŽæ³¨é‡ŠåQˆAnnotationåQ‰çš„配置有越来越‹¹è¡Œçš„趋势,Spring 2.5 ™åºåº”˜q™ç§­‘‹åŠ¿åQŒæä¾›äº†(ji¨£n)完全åŸÞZºŽæ³¨é‡Šé…ç½® Bean、装é…?Bean 的功能,æ‚(zh¨¨n)¨å¯ä»¥ä‹É用基于注释的 Spring IoC 替换原来åŸÞZºŽ XML 的配¾|®ã€‚本文通过实例详细讲述äº?Spring 2.5 åŸÞZºŽæ³¨é‡Š IoC 功能的ä‹É用ã€?/p>

<!--START RESERVED FOR FUTURE USE INCLUDE FILES--><!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters --><!--END RESERVED FOR FUTURE USE INCLUDE FILES-->

概述

注释配置相对äº?XML 配置å…ähœ‰å¾ˆå¤šçš„优势:(x¨¬)

  • 它可以充分利ç”?Java 的反ž®„机制获取类¾l“构信息åQŒè¿™äº›ä¿¡æ¯å¯ä»¥æœ‰æ•ˆå‡ž®‘配¾|®çš„工作。如使用 JPA 注释配置 ORM 映射æ—Óž¼Œæˆ‘们ž®×ƒ¸éœ€è¦æŒ‡å®?PO 的属性名、类型等信息åQŒå¦‚果关¾p»è¡¨å­—段å’?PO 属性名、类型都一è‡ß_(d¨¢)¼Œæ‚(zh¨¨n)¨ç”šè‡Ïx(ch¨®ng)— éœ€¾~–写ä»ÕdŠ¡å±žæ€§æ˜ ž®„ä¿¡æ¯â€”â€”å› ä¸ø™¿™äº›ä¿¡æ¯éƒ½å¯ä»¥é€šè¿‡ Java 反射机制获取ã€?
  • 注释å’?Java 代码位于一个文件中åQŒè€?XML 配置采用独立的配¾|®æ–‡ä»Óž¼Œå¤§å¤šæ•°é…¾|®ä¿¡æ¯åœ¨½E‹åºå¼€å‘完成后都不ä¼?x¨¬)è°ƒæ•ß_(d¨¢)¼Œå¦‚果配置信息å’?Java 代码攑֜¨ä¸€èµøP¼Œæœ‰åŠ©äºŽå¢žå¼ºç¨‹åºçš„å†…èšæ€§ã€‚è€Œé‡‡ç”¨ç‹¬ç«‹çš„ XML 配置文äšgåQŒç¨‹åºå‘˜åœ¨ç¼–写一个功能时åQŒå¾€å¾€éœ€è¦åœ¨½E‹åºæ–‡äšg和配¾|®æ–‡ä»¶ä¸­ä¸åœåˆ‡æ¢åQŒè¿™¿Uæ€ç»´ä¸Šçš„不连贯会(x¨¬)降低开发效率ã€?

因此在很多情况下åQŒæ³¨é‡Šé…¾|®æ¯” XML 配置更受‹Æ¢è¿ŽåQŒæ³¨é‡Šé…¾|®æœ‰˜q›ä¸€æ­¥æµè¡Œçš„­‘‹åŠ¿ã€‚Spring 2.5 的一大增强就是引入了(ji¨£n)很多注释¾c»ï¼ŒçŽ°åœ¨æ‚(zh¨¨n)¨å·²¾lå¯ä»¥ä‹É用注释配¾|®å®Œæˆå¤§éƒ¨åˆ† XML 配置的功能。在˜q™ç¯‡æ–‡ç« é‡Œï¼Œæˆ‘们ž®†å‘æ‚(zh¨¨n)¨è®²˜qîC‹É用注释进è¡?Bean 定义和依赖注入的内容ã€?/p>

 

 

 

使用 @Autowired 注释

Spring 2.5 引入äº?@Autowired 注释åQŒå®ƒå¯ä»¥å¯¹ç±»æˆå‘˜å˜é‡ã€æ–¹æ³•及(qi¨¢ng)构造函数进行标注,完成自动装配的工作ã€?/p>

Spring 通过一ä¸?BeanPostProcessor å¯?@Autowired ˜q›è¡Œè§£æžåQŒæ‰€ä»¥è¦è®?@Autowired 起作用必™åÖMº‹å…ˆåœ¨ Spring 容器中声æ˜?AutowiredAnnotationBeanPostProcessor Beanã€?/p>

 

 

在Spring中配¾|®å¦‚下:(x¨¬)

<!-- è¯?BeanPostProcessor ž®†è‡ªåЍè“v作用åQŒå¯¹æ ‡æ³¨ @Autowired çš?Bean ˜q›è¡Œè‡ªåŠ¨æ³¨å…¥ -->
    <bean class="org.springframework.beans.factory.annotation.
        AutowiredAnnotationBeanPostProcessor"/>
å½?Spring 容器启动æ—Óž¼ŒAutowiredAnnotationBeanPostProcessor ž®†æ‰«æ?Spring 容器中所æœ?BeanåQŒå½“发现 Bean 中拥æœ?@Autowired 注释时就扑ֈ°å’Œå…¶åŒšw…åQˆé»˜è®¤æŒ‰¾cÕdž‹åŒšw…åQ‰çš„ BeanåQŒåƈ注入到对应的地方中去ã€?/p>

按照上面的配¾|®ï¼ŒSpring ž®†ç›´æŽ¥é‡‡ç”?Java 反射机制å¯?Boss 中的 car å’?office ˜q™ä¸¤ä¸ªç§æœ‰æˆå‘˜å˜é‡è¿›è¡Œè‡ªåŠ¨æ³¨å…¥ã€‚æ‰€ä»¥å¯¹æˆå‘˜å˜é‡ä½¿ç”¨ @Autowired 后,æ‚(zh¨¨n)¨å¤§å¯å°†å®ƒä»¬çš?setter æ–ÒŽ(gu¨©)³•åQ?code>setCar() å’?setOffice()åQ‰ä»Ž Boss 中删除ã€?/p>

当然åQŒæ?zh¨¨n)¨ä¹Ÿå¯ä»¥é€šè¿‡ @Autowired å¯ÒŽ(gu¨©)–¹æ³•或构造函数进行标注,

 

当候é€?Bean æ•°ç›®ä¸äØ“(f¨´) 1 时的应对æ–ÒŽ(gu¨©)³•

在默认情况下使用 @Autowired 注释˜q›è¡Œè‡ªåŠ¨æ³¨å…¥æ—Óž¼ŒSpring 容器中匹配的候é€?Bean 数目必须有且仅有一个。当找不åˆîC¸€ä¸ªåŒ¹é…çš„ Bean æ—Óž¼ŒSpring 容器ž®†æŠ›å‡?BeanCreationException 异常åQŒåƈ指出必须臛_°‘拥有一个匹配的 Beanã€?/p>

 

当不能确å®?Spring 容器中一定拥有某个类çš?Bean æ—Óž¼Œå¯ä»¥åœ¨éœ€è¦è‡ªåŠ¨æ³¨å…¥è¯¥¾c?Bean 的地方可以ä‹Éç”?@Autowired(required = false)åQŒè¿™½{‰äºŽå‘Šè¯‰ SpringåQšåœ¨æ‰¾ä¸åˆ°åŒ¹é…?Bean 时也不报错ã€?/p>

 

一般情况下åQŒä‹Éç”?@Autowired 的地斚wƒ½æ˜¯éœ€è¦æ³¨å…?Bean 的,使用äº?ji¨£n)自动注入而又允许不注入的情况一般仅ä¼?x¨¬)在开发期或测试期¼„°åˆ°åQˆå¦‚ä¸ÞZº†(ji¨£n)快速启åŠ?Spring 容器åQŒä»…引入一些模块的 Spring 配置文äšgåQ‰ï¼Œæ‰€ä»?@Autowired(required = false) ä¼?x¨¬)很ž®‘用到ã€?/p>

和找不到一个类型匹é…?Bean 相反的一个错误是åQšå¦‚æž?Spring 容器中拥有多个候é€?BeanåQŒSpring 容器在启动时也会(x¨¬)抛出 BeanCreationException 异常ã€?/p>

 

Spring 允许我们通过 @Qualifier 注释指定注入 Bean 的名¿UŽÍ¼Œ˜q™æ ·æ­§ä¹‰ž®±æ¶ˆé™¤äº†(ji¨£n)åQŒå¯ä»¥é€šè¿‡ä¸‹é¢çš„æ–¹æ³•解军_¼‚常:(x¨¬)


清单 13. 使用 @Qualifier 注释指定注入 Bean 的名¿U?/strong>

            @Autowired
            public void setOffice(@Qualifier("office")Office office) {
            this.office = office;
            }
            

@Qualifier("office") 中的 office æ˜?Bean 的名¿UŽÍ¼Œæ‰€ä»?@Autowired å’?@Qualifier ¾l“合使用æ—Óž¼Œè‡ªåŠ¨æ³¨å…¥çš„ç­–ç•¥å°±ä»?byType 转变æˆ?byName äº?ji¨£n)ã€?code>@Autowired 可以å¯ÒŽ(gu¨©)ˆå‘˜å˜é‡ã€æ–¹æ³•以å?qi¨¢ng)构造函数进行注释,è€?@Qualifier 的标注对象是成员变量、方法入参、构造函数入参。正是由于注释对象的不同åQŒæ‰€ä»?Spring 不将 @Autowired å’?@Qualifier ¾lŸä¸€æˆä¸€ä¸ªæ³¨é‡Šç±»ã€‚下面是å¯ÒŽ(gu¨©)ˆå‘˜å˜é‡å’Œæž„造函数入参进行注释的代码åQ?/p>

å¯ÒŽ(gu¨©)ˆå‘˜å˜é‡è¿›è¡Œæ³¨é‡Šï¼š(x¨¬)

 

å¯ÒŽ(gu¨©)ˆå‘˜å˜é‡ä‹Éç”?@Qualifier 注释

            public class Boss {
            @Autowired
            private Car car;
            @Autowired
            @Qualifier("office")
            private Office office;
            …
            }
            

å¯ÒŽ(gu¨©)ž„造函数入参进行注释:(x¨¬)


清单 15. å¯ÒŽ(gu¨©)ž„造函数变量ä‹Éç”?@Qualifier 注释

            public class Boss {
            private Car car;
            private Office office;
            @Autowired
            public Boss(Car car , @Qualifier("office")Office office){
            this.car = car;
            this.office = office ;
            }
            }
            

@Qualifier 只能å’?@Autowired ¾l“合使用åQŒæ˜¯å¯?@Autowired 有益的补充。一般来è®ÔŒ¼Œ@Qualifier å¯ÒŽ(gu¨©)–¹æ³•签名中入参˜q›è¡Œæ³¨é‡Šä¼?x¨¬)降低代码的可读性,而对成员变量注释则相对好一些ã€?/p>

 

使用 JSR-250 的注�/span>

Spring 不但支持自己定义çš?@Autowired 的注释,˜q˜æ”¯æŒå‡ ä¸ªç”± JSR-250 规范定义的注释,它们分别æ˜?@Resourceã€?code>@PostConstruct 以及(qi¨¢ng) @PreDestroyã€?/p>

@Resource

@Resource 的作用相当于 @AutowiredåQŒåªä¸è¿‡ @Autowired æŒ?byType 自动注入åQŒé¢ @Resource 默认æŒ?byName 自动注入¾|¢äº†(ji¨£n)ã€?code>@Resource 有两个属性是比较重要的,分别æ˜?name å’?typeåQŒSpring ž®?@Resource 注释çš?name å±žæ€§è§£æžäØ“(f¨´) Bean 的名字,è€?type 属性则解析ä¸?Bean 的类型。所以如果ä‹Éç”?name 属性,则ä‹Éç”?byName 的自动注入策略,而ä‹Éç”?type 属性时则ä‹Éç”?byType 自动注入½{–略。如果既不指å®?name 也不指定 type 属性,˜q™æ—¶ž®†é€šè¿‡åå°„机制使用 byName 自动注入½{–ç•¥ã€?/p>

Resource 注释¾cÖM½äº?Spring 发布包的 lib/j2ee/common-annotations.jar ¾cÕdŒ…中,因此在ä‹É用之前必™åÕd°†å…¶åŠ å…¥åˆ°™å¹ç›®çš„类库中。来看一个ä‹Éç”?@Resource 的例子:(x¨¬)


清单 16. 使用 @Resource 注释�Boss.java

            package com.baobaotao;
            import javax.annotation.Resource;
            public class Boss {
            // 自动注入¾cÕdž‹ä¸?Car çš?Bean
            @Resource
            private Car car;
            // 自动注入 bean 名称�office �Bean
            @Resource(name = "office")
            private Office office;
            }
            

一般情况下åQŒæˆ‘们无需使用¾cÖM¼¼äº?@Resource(type=Car.class) çš„æ³¨é‡Šæ–¹å¼ï¼Œå› äØ“(f¨´) Bean 的类型信息可以通过 Java 反射从代码中获取ã€?/p>

要让 JSR-250 的注释生效,除了(ji¨£n)åœ?Bean ¾cÖM¸­æ ‡æ³¨˜q™äº›æ³¨é‡Šå¤–,˜q˜éœ€è¦åœ¨ Spring 容器中注册一个负责处理这些注释的 BeanPostProcessoråQ?/p>

 

<bean
            class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"/>
            

CommonAnnotationBeanPostProcessor 实现äº?BeanPostProcessor 接口åQŒå®ƒè´Ÿè´£æ‰«æä½¿ç”¨äº?JSR-250 注释çš?BeanåQŒåƈ对它们进行相应的操作ã€?/p>

@PostConstruct å’?@PreDestroy

Spring 容器中的 Bean 是有生命周期的,Spring 允许åœ?Bean 在初始化完成后以å?Bean 销毁前执行特定的操作,æ‚(zh¨¨n)¨æ—¢å¯ä»¥é€šè¿‡å®žçް InitializingBean/DisposableBean 接口来定制初始化之后 / 销毁之前的操作æ–ÒŽ(gu¨©)³•åQŒä¹Ÿå¯ä»¥é€šè¿‡ <bean> 元素çš?init-method/destroy-method 属性指定初始化之后 / 销毁之前调用的操作æ–ÒŽ(gu¨©)³•。关äº?Spring 的生命周期,½W”者在《精é€?Spring 2.x—企业应用开发精解》第 3 章进行了(ji¨£n)详细的描˜qŽÍ¼Œæœ‰å…´­‘£çš„读者可以查阅ã€?/p>

JSR-250 为初始化之后/销毁之前方法的指定定义äº?ji¨£n)两个注释类åQŒåˆ†åˆ«æ˜¯ @PostConstruct å’?@PreDestroyåQŒè¿™ä¸¤ä¸ªæ³¨é‡Šåªèƒ½åº”用于方法上。标注了(ji¨£n) @PostConstruct 注释的方法将在类实例化后调用åQŒè€Œæ ‡æ³¨äº†(ji¨£n) @PreDestroy 的方法将在类销毁之前调用ã€?/p>


清单 17. 使用 @PostConstruct �@PreDestroy 注释�Boss.java

            package com.baobaotao;
            import javax.annotation.Resource;
            import javax.annotation.PostConstruct;
            import javax.annotation.PreDestroy;
            public class Boss {
            @Resource
            private Car car;
            @Resource(name = "office")
            private Office office;
            @PostConstruct
            public void postConstruct1(){
            System.out.println("postConstruct1");
            }
            @PreDestroy
            public void preDestroy1(){
            System.out.println("preDestroy1");
            }
            …
            }
            

æ‚(zh¨¨n)¨åªéœ€è¦åœ¨æ–ÒŽ(gu¨©)³•前标æ³?@PostConstruct æˆ?@PreDestroyåQŒè¿™äº›æ–¹æ³•å°±ä¼?x¨¬)åœ?Bean 初始化后或销毁之前被 Spring 容器执行äº?ji¨£n)ã€?/p>

我们知道åQŒä¸½Ž¡æ˜¯é€šè¿‡å®žçް InitializingBean/DisposableBean 接口åQŒè¿˜æ˜¯é€šè¿‡ <bean> 元素çš?init-method/destroy-method 属性进行配¾|®ï¼Œéƒ½åªèƒ½äØ“(f¨´) Bean 指定一个初始化 / 销毁的æ–ÒŽ(gu¨©)³•。但是ä‹Éç”?@PostConstruct å’?@PreDestroy 注释却可以指定多个初始化 / 销毁方法,那些被标æ³?@PostConstruct æˆ?@PreDestroy 注释的方法都ä¼?x¨¬)在初始å?/ 销毁时被执行ã€?/p>

通过以下的测试代码,æ‚(zh¨¨n)¨å°†å¯ä»¥çœ‹åˆ° Bean 的初始化 / 销毁方法是如何被执行的åQ?/p>


清单 18. ‹¹‹è¯•¾cÖM»£ç ?/strong>

            package com.baobaotao;
            import org.springframework.context.support.ClassPathXmlApplicationContext;
            public class AnnoIoCTest {
            public static void main(String[] args) {
            String[] locations = {"beans.xml"};
            ClassPathXmlApplicationContext ctx =
            new ClassPathXmlApplicationContext(locations);
            Boss boss = (Boss) ctx.getBean("boss");
            System.out.println(boss);
            ctx.destroy();// 关闭 Spring 容器åQŒä»¥è§¦å‘ Bean 销毁方法的执行
            }
            }
            

˜q™æ—¶åQŒæ?zh¨¨n)¨ž®†çœ‹åˆ°æ ‡æ³¨äº?ji¨£n) @PostConstruct çš?postConstruct1() æ–ÒŽ(gu¨©)³•ž®†åœ¨ Spring 容器启动æ—Óž¼Œåˆ›å¾ Boss Bean 的时候被触发执行åQŒè€Œæ ‡æ³¨äº†(ji¨£n) @PreDestroy 注释çš?preDestroy1() æ–ÒŽ(gu¨©)³•ž®†åœ¨ Spring 容器关闭前销æ¯?Boss Bean 的时候被触发执行ã€?/p>





回页�/span>

使用 <context:annotation-config/> ½Ž€åŒ–配¾|?/span>

Spring 2.1 æ·ÕdŠ äº?ji¨£n)一个新çš?context çš?Schema 命名½Iºé—´åQŒè¯¥å‘½å½Iºé—´å¯ÒŽ(gu¨©)³¨é‡Šé©±åŠ¨ã€å±žæ€§æ–‡ä»¶å¼•å…¥ã€åŠ è½½æœŸ¾l‡å…¥½{‰åŠŸèƒ½æä¾›äº†(ji¨£n)便捷的配¾|®ã€‚我们知道注释本íw«æ˜¯ä¸ä¼š(x¨¬)做ä“Q何事情的åQŒå®ƒä»…提供元数据信息。要使元数据信息真正起作用,必须让负责处理这些元数据的处理器工作èµäh¥ã€?

而我们前面所介绍çš?AutowiredAnnotationBeanPostProcessor å’?CommonAnnotationBeanPostProcessor ž®±æ˜¯å¤„理˜q™äº›æ³¨é‡Šå…ƒæ•°æ®çš„处理器。但是直接在 Spring 配置文äšg中定义这äº?Bean 昑־—比较½W¨æ‹™ã€‚Spring 为我们提供了(ji¨£n)一¿Uæ–¹ä¾¿çš„æ³¨å†Œ˜q™äº› BeanPostProcessor 的方式,˜q™å°±æ˜?<context:annotation-config/>。请看下面的配置åQ?/p>


清单 19. 调整 beans.xml 配置文äšg

            <?xml version="1.0" encoding="UTF-8" ?>
            <beans xmlns="http://www.springframework.org/schema/beans"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xmlns:context="http://www.springframework.org/schema/context"
            xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context-2.5.xsd">
            <context:annotation-config/>
            <bean id="boss" class="com.baobaotao.Boss"/>
            <bean id="office" class="com.baobaotao.Office">
            <property name="officeNo" value="001"/>
            </bean>
            <bean id="car" class="com.baobaotao.Car" scope="singleton">
            <property name="brand" value=" ¾U¢æ—— CA72"/>
            <property name="price" value="2000"/>
            </bean>
            </beans>
            

<context:annotationconfig/> ž®†éšå¼åœ°å?Spring 容器注册 AutowiredAnnotationBeanPostProcessorã€?code>CommonAnnotationBeanPostProcessorã€?code>PersistenceAnnotationBeanPostProcessor 以及(qi¨¢ng) equiredAnnotationBeanPostProcessor ˜q?4 ä¸?BeanPostProcessorã€?/p>

在配¾|®æ–‡ä»¶ä¸­ä½¿ç”¨ context 命名½Iºé—´ä¹‹å‰åQŒå¿…™åÕdœ¨ <beans> 元素中声æ˜?context 命名½Iºé—´ã€?/p>





回页�/span>

使用 @Component

虽然我们可以通过 @Autowired æˆ?@Resource åœ?Bean ¾cÖM¸­ä½¿ç”¨è‡ªåŠ¨æ³¨å…¥åŠŸèƒ½åQŒä½†æ˜?Bean ˜q˜æ˜¯åœ?XML æ–‡äšg中通过 <bean> ˜q›è¡Œå®šä¹‰ —â€?也就是说åQŒåœ¨ XML 配置文äšg中定ä¹?BeanåQŒé€šè¿‡ @Autowired æˆ?@Resource ä¸?Bean 的成员变量、方法入参或构造函数入参提供自动注入的功能。能否也通过注释定义 BeanåQŒä»Ž XML 配置文äšg中完全移é™?Bean 定义的配¾|®å‘¢åQŸç­”案是肯定的,我们通过 Spring 2.5 提供çš?@Component 注释ž®±å¯ä»¥è¾¾åˆ°è¿™ä¸ªç›®æ ‡äº†(ji¨£n)ã€?/p>

下面åQŒæˆ‘们完全ä‹É用注释定ä¹?Bean òq¶å®Œæˆ?Bean 之间装配åQ?/p>


清单 20. 使用 @Component 注释�Car.java

            package com.baobaotao;
            import org.springframework.stereotype.Component;
            @Component
            public class Car {
            …
            }
            

仅需要在¾cÕd®šä¹‰å¤„åQŒä‹Éç”?@Component 注释ž®±å¯ä»¥å°†ä¸€ä¸ªç±»å®šä¹‰äº?Spring 容器中的 Bean。下面的代码ž®?Office 定义ä¸ÞZ¸€ä¸?BeanåQ?/p>


清单 21. 使用 @Component 注释�Office.java

            package com.baobaotao;
            import org.springframework.stereotype.Component;
            @Component
            public class Office {
            private String officeNo = "001";
            …
            }
            

˜q™æ ·åQŒæˆ‘们就可以åœ?Boss ¾cÖM¸­é€šè¿‡ @Autowired 注入前面定义çš?Car å’?Office Bean äº?ji¨£n)ã€?/p>


清单 22. 使用 @Component 注释�Boss.java

            package com.baobaotao;
            import org.springframework.beans.factory.annotation.Autowired;
            import org.springframework.beans.factory.annotation.Required;
            import org.springframework.beans.factory.annotation.Qualifier;
            import org.springframework.stereotype.Component;
            @Component("boss")
            public class Boss {
            @Autowired
            private Car car;
            @Autowired
            private Office office;
            …
            }
            

@Component 有一个可选的入参åQŒç”¨äºŽæŒ‡å®?Bean 的名¿UŽÍ¼Œåœ?Boss 中,我们ž®±å°† Bean 名称定义ä¸?#8220;boss”。一般情况下åQŒBean 都是 singleton 的,需要注å…?Bean 的地方仅需要通过 byType ½{–ç•¥ž®±å¯ä»¥è‡ªåŠ¨æ³¨å…¥äº†(ji¨£n)åQŒæ‰€ä»¥å¤§å¯ä¸å¿…指å®?Bean 的名¿U°ã€?/p>

在ä‹Éç”?@Component 注释后,Spring 容器必须启用¾cÀL‰«ææœºåˆ¶ä»¥å¯ç”¨æ³¨é‡Šé©±åЍ Bean 定义和注释驱åŠ?Bean 自动注入的策略。Spring 2.5 å¯?context 命名½Iºé—´˜q›è¡Œäº?ji¨£n)扩展,提供了(ji¨£n)这一功能åQŒè¯·çœ‹ä¸‹é¢çš„配置åQ?/p>


清单 23. ½Ž€åŒ–版çš?beans.xml

            <?xml version="1.0" encoding="UTF-8" ?>
            <beans xmlns="http://www.springframework.org/schema/beans"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xmlns:context="http://www.springframework.org/schema/context"
            xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context-2.5.xsd">
            <context:component-scan base-package="com.baobaotao"/>
            </beans>
            

˜q™é‡ŒåQŒæ‰€æœ‰é€šè¿‡ <bean> 元素定义 Bean 的配¾|®å†…容已¾lè¢«¿U»é™¤åQŒä»…需要添加一è¡?<context:component-scan/> 配置ž®Þp§£å†Ïx(ch¨®ng)‰€æœ‰é—®é¢˜ä(sh¨´)º†(ji¨£n)——Spring XML 配置文äšg得到äº?ji¨£n)极致的½Ž€åŒ–(当然配置元数据还是需要的åQŒåªä¸è¿‡ä»¥æ³¨é‡ŠåŞ式存在çÅžäº?ji¨£n)ï¼?j¨ª)ã€?lt;context:component-scan/> çš?base-package 属性指定了(ji¨£n)需要扫描的¾cÕdŒ…åQŒç±»åŒ…及(qi¨¢ng)å…‰™€’归子包中所有的¾c»éƒ½ä¼?x¨¬)被处理ã€?/p>

<context:component-scan/> ˜q˜å…è®¸å®šä¹‰è¿‡æ»¤å™¨ž®†åŸºåŒ…下的某些类¾U›_…¥æˆ–排除。Spring 支持以下 4 ¿Uç±»åž‹çš„˜q‡æ×o(h¨´)方式åQŒé€šè¿‡ä¸‹è¡¨è¯´æ˜ŽåQ?/p>


è¡?1. 扫描˜q‡æ×o(h¨´)方式

˜q‡æ×o(h¨´)器类åž?/th> 说明
注释 假如 com.baobaotao.SomeAnnotation 是一个注释类åQŒæˆ‘们可以将使用该注释的¾c»è¿‡æ»¤å‡ºæ¥ã€?/td>
¾cÕdæŒ‡å®š 通过全限定类名进行过滤,如æ?zh¨¨n)¨å¯ä»¥æŒ‡å®šž?com.baobaotao.Boss ¾U›_…¥æ‰«æåQŒè€Œå°† com.baobaotao.Car 排除在外ã€?/td>
正则表达å¼?/td> 通过正则表达式定义过滤的¾c»ï¼Œå¦‚下所½Cºï¼š(x¨¬) com\.baobaotao\.Default.*
AspectJ 表达å¼?/td> 通过 AspectJ 表达式定义过滤的¾c»ï¼Œå¦‚下所½Cºï¼š(x¨¬) com. baobaotao..*Service+

下面是一个简单的例子åQ?/p>

 

<context:component-scan base-package="com.baobaotao">
            <context:include-filter type="regex"
            expression="com\.baobaotao\.service\..*"/>
            <context:exclude-filter type="aspectj"
            expression="com.baobaotao.util..*"/>
            </context:component-scan>
            

值得注意的是 <context:component-scan/> 配置™å¹ä¸ä½†å¯ç”¨äº†(ji¨£n)对类包进行扫描以实施注释驱动 Bean 定义的功能,同时˜q˜å¯ç”¨äº†(ji¨£n)注释驱动自动注入的功能(卌™¿˜éšå¼åœ°åœ¨å†…部注册äº?AutowiredAnnotationBeanPostProcessor å’?CommonAnnotationBeanPostProcessoråQ‰ï¼Œå› æ­¤å½“ä‹Éç”?<context:component-scan/> 后,ž®±å¯ä»¥å°† <context:annotation-config/> ¿U»é™¤äº?ji¨£n)ã€?/p>

默认情况下通过 @Component 定义çš?Bean 都是 singleton 的,如果需要ä‹É用其它作用范围的 BeanåQŒå¯ä»¥é€šè¿‡ @Scope 注释来达到目标,如以下代码所½Cºï¼š(x¨¬)


清单 24. 通过 @Scope 指定 Bean 的作用范�/strong>

            package com.baobaotao;
            import org.springframework.context.annotation.Scope;
            …
            @Scope("prototype")
            @Component("boss")
            public class Boss {
            …
            }
            

˜q™æ ·åQŒå½“ä»?Spring 容器中获å?boss Bean æ—Óž¼Œæ¯æ¬¡˜q”回的都是新的实例了(ji¨£n)ã€?/p>





回页�/span>

采用å…ähœ‰ç‰ÒŽ(gu¨©)®Šè¯­ä¹‰çš„æ³¨é‡?/span>

Spring 2.5 中除äº?ji¨£n)提ä?@Component 注释外,˜q˜å®šä¹‰äº†(ji¨£n)几个拥有ç‰ÒŽ(gu¨©)®Šè¯­ä¹‰çš„æ³¨é‡Šï¼Œå®ƒä»¬åˆ†åˆ«æ˜¯ï¼š(x¨¬)@Repositoryã€?code>@Service å’?@Controller。在目前çš?Spring 版本中,˜q?3 个注释和 @Component 是等效的åQŒä½†æ˜¯ä»Žæ³¨é‡Š¾cȝš„命名上,很容易看å‡?gu¨®)™¿?3 个注释分别和持久层、业务层和控制层åQˆWeb 层)(j¨ª)相对应。虽然目前这 3 个注释和 @Component 相比没有什么新意,ä½?Spring ž®†åœ¨ä»¥åŽçš„版本中为它们添加特ŒDŠçš„功能。所以,如果 Web 应用½E‹åºé‡‡ç”¨äº?ji¨£n)经典的三层分层¾l“构的话åQŒæœ€å¥½åœ¨æŒä¹…层、业务层和控制层分别采用 @Repositoryã€?code>@Service å’?@Controller 对分层中的类˜q›è¡Œæ³¨é‡ŠåQŒè€Œç”¨ @Component 寚w‚£äº›æ¯”较中立的¾c»è¿›è¡Œæ³¨é‡Šã€?/p>





回页�/span>

注释配置�XML 配置的适用场合

是否有了(ji¨£n)˜q™äº› IOC 注释åQŒæˆ‘们就可以完全摒除原来 XML 配置的方式呢åQŸç­”案是否定的。有以下几点原因åQ?/p>

  • 注释配置不一定在先天上优?sh¨´)?XML 配置。如æž?Bean 的依赖关¾pÀL˜¯å›ºå®šçš„,åQˆå¦‚ Service 使用äº?ji¨£n)哪几ä¸?DAO ¾c»ï¼‰(j¨ª)åQŒè¿™¿Ué…¾|®ä¿¡æ¯ä¸ä¼?x¨¬)在部çÖv时发生调æ•ß_(d¨¢)¼Œé‚£ä¹ˆæ³¨é‡Šé…ç½®ä¼˜ä(sh¨´)ºŽ XML 配置åQ›åä¹‹å¦‚果这¿Uä¾èµ–å…³¾pÖM¼š(x¨¬)在部¾|²æ—¶å‘生调整åQŒXML 配置昄¡„¶åˆä¼˜?sh¨´)ºŽæ³¨é‡Šé…¾|®ï¼Œå› äØ“(f¨´)注释是对 Java 源代码的调整åQŒæ?zh¨¨n)¨éœ€è¦é‡æ–°æ”¹å†™æºä»£ç òq‰™‡æ–°ç¼–译才可以实施调整ã€?
  • 如果 Bean 不是自己¾~–写的类åQˆå¦‚ JdbcTemplateã€?code>SessionFactoryBean ½{‰ï¼‰(j¨ª)åQŒæ³¨é‡Šé…¾|®å°†æ— æ³•实施åQŒæ­¤æ—?XML 配置是唯一可用的方式ã€?
  • 注释配置往往是类¾U§åˆ«çš„,è€?XML 配置则可以表现得更加灉|´»ã€‚比如相比于 @Transaction 事务注释åQŒä‹Éç”?aop/tx 命名½Iºé—´çš„事务配¾|®æ›´åŠ çµ‹zÕd’Œ½Ž€å•ã€?

所以在实现应用中,我们往往需要同时ä‹É用注释配¾|®å’Œ XML 配置åQŒå¯¹äºŽç±»¾U§åˆ«ä¸”不ä¼?x¨¬)发生变动的配置可以优先考虑注释配置åQ›è€Œå¯¹äºŽé‚£äº›ç¬¬ä¸‰æ–¹¾cÖM»¥å?qi¨¢ng)容易发生调整的配置则应优先考虑使用 XML 配置。Spring ä¼?x¨¬)在具体实æ–?Bean 创徏å’?Bean 注入之前ž®†è¿™ä¸¤ç§é…ç½®æ–¹å¼çš„元信息融合在一赗÷€?/p>





回页�/span>

ž®ç»“

Spring åœ?2.1 以后å¯ÒŽ(gu¨©)³¨é‡Šé…¾|®æä¾›äº†(ji¨£n)å¼ºåŠ›çš„æ”¯æŒï¼Œæ³¨é‡Šé…ç½®åŠŸèƒ½æˆäØ“(f¨´) Spring 2.5 的最大的亮点之一。合理地使用 Spring 2.5 的注释配¾|®ï¼Œå¯ä»¥æœ‰æ•ˆå‡å°‘配置的工作量åQŒæé«˜ç¨‹åºçš„内聚性。但是这òq¶ä¸æ„å‘³ç€ä¼ ç»Ÿ XML 配置ž®†èµ°å‘消亡,在第三方¾c?Bean 的配¾|®ï¼Œä»¥åŠ(qi¨¢ng)那些诸如数据源、缓存池、持久层操作模板¾c…R€äº‹åŠ¡ç®¡ç†ç­‰å†…å®¹çš„é…¾|®ä¸ŠåQŒXML 配置依然拥有不可替代的地位ã€?/p>

]]>
Spring控制反è{的通俗解释【è{ã€?/title><link>http://www.aygfsteel.com/EricGu/archive/2010/12/15/340757.html</link><dc:creator>Eric Gu</dc:creator><author>Eric Gu</author><pubDate>Wed, 15 Dec 2010 03:39:00 GMT</pubDate><guid>http://www.aygfsteel.com/EricGu/archive/2010/12/15/340757.html</guid><wfw:comment>http://www.aygfsteel.com/EricGu/comments/340757.html</wfw:comment><comments>http://www.aygfsteel.com/EricGu/archive/2010/12/15/340757.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/EricGu/comments/commentRss/340757.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/EricGu/services/trackbacks/340757.html</trackback:ping><description><![CDATA[<div class="wmqeeuq" id="blog_text" class="cnt"> <p><font size="2" face="宋体">什么叫控制反è{呢?套用好莱坞的一句名­a€ž®±æ˜¯åQšä½ å‘†ç€åˆ«åЍåQŒåˆ°æ—¶æˆ‘ä¼?x¨¬)找你ã€?<br /> 什么意思呢åQŸå°±å¥½æ¯”一个皇帝和太监 <br /> </font><font size="2"><font face="宋体"><font color="#3366ff">有一天皇帝想宠幸某个¾ŸŽå¥³åQŒäºŽæ˜¯è·Ÿå¤ªç›‘è¯ß_(d¨¢)¼Œä»Šå¤œæˆ‘要宠幸¾ŸŽå¥³ <br /> 皇帝往往不会(x¨¬)告诉太监åQŒä»Šæ™šå‡ ç‚¹ä¼š(x¨¬)回宫åQŒä¼š(x¨¬)回哪张龙床,他只ä¼?x¨¬)告诉太监他要哪位美å?/font> <br /> </font></font><font size="2"><font face="宋体"><font color="#ff6600">其它一切都交由太监åŽÕd®‰æŽ’,åˆîCº†(ji¨£n)晚上皇帝回宫æ—Óž¼Œè‡ªç„¶ä¼?x¨¬)有¾ŸŽå¥³å‡ºçŽ°åœ¨çš‡å¸çš„é¾™åºŠä?<br /> ˜q™å°±æ˜¯æŽ§åˆ¶åè½¬ï¼Œè€ŒæŠŠ¾ŸŽå¥³é€åˆ°çš‡å¸çš„寝宫里面去ž®±æ˜¯æ³¨å°„</font> <br /> <font color="#ff0000">太监ž®±æ˜¯æ˜¯æ¡†æž‰™‡Œé¢çš„æ³¨å°„控制器类</font>BeanFactoryåQŒè´Ÿè´£æ‰¾åˆ°ç¾Žå¥›_ƈ送到龙床上去 <br /> <font color="#ff0000">整个后宫可以看成是Spring框架</font>åQŒç¾Žå¥›_°±æ˜¯Spring控制下的JavaBean <br /> </font></font><font color="#339966" size="2" face="宋体">而传¾lŸçš„æ¨¡å¼ž®±æ˜¯ä¸€ä¸ªé¥¥æ¸´ç”·åŽÀL‰¾ž®å§å‡ºå° <br /> </font><font size="2"><font face="宋体"><font color="#3366ff">æ‰ùN¢†ç­ï¼Œå¸®åŠ©¾l™ä»‹¾lä¸€ä¸ªäº‘云,于是领班ž®±å¼€å§‹ç»™ä»–å¼ ¾|?br /> 介绍一个合适的¾l™ä»–åQŒå®Œäº‹åŽåQŒå†æŠŠå°å§è¿˜¾l™é¢†ç­ï¼Œä¸‹æ¬¡å†æ¥</font> <br /> </font></font><font size="2"><font face="宋体"><font color="#ff6600">˜q™ä¸ª˜q‡ç¨‹ä¸­ï¼Œé¢†ç­ž®±æ˜¯æŸ¥è¯¢ä¸Šä¸‹æ–‡ContextåQŒé¢†ç­çš„一个职能就是给客户扑ֈ°ä»–们所要的ž®å§ <br /> ˜q™å°±æ˜¯lookup()æ–ÒŽ(gu¨©)³•åQŒé¢†ç­æ‰‹ä¸­çš„ž®å§åå½•ž®±æ˜¯JNDI//Java Naming and Directory Interface <br /> </font><font color="#ff0000">ž®å§ž®±æ˜¯EJB</font>åQ?font color="#0000ff">饥æÍ(f¨´)ç”äh˜¯å®¢æˆ·ç«?/font>åQ?font color="#ff0000">青楼是EJB容器</font> <br /> 看到区别äº?ji¨£n)么åQ?/font></font></p> <p><font size="2"><font color="#993366" face="宋体">饥æÍ(f¨´)男去扑ְå§å‡ºå°å¾ˆéºÈƒ¦(ch¨³)åQŒä¸ä»…得找,用完后还得把ž®å§¾l™è¿˜å›žåŽ»</font></font></p> <p><font color="#ff00ff"><font face="宋体"><font size="2">而皇帝爽¾˜ÖMº†(ji¨£n)åQŒä»€ä¹ˆéƒ½ä¸ç”¨½Ž¡ï¼Œäº¤ç»™å¤ªç›‘åŽÕd¤„理,控制权è{¿UÕdˆ°å¤ªç›‘手中åŽÖMº†(ji¨£n)</font><font size="2">而不是皇帝,</font></font></font></p> <p><font color="#ff00ff"><font size="2" face="宋体">必要时候由太监¾l™æ³¨ž®„è¿›åŽÕd°±å¯ä»¥äº?/font></font></p> </div> <br /> <img src ="http://www.aygfsteel.com/EricGu/aggbug/340757.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/EricGu/" target="_blank">Eric Gu</a> 2010-12-15 11:39 <a href="http://www.aygfsteel.com/EricGu/archive/2010/12/15/340757.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[hibernate]注解的说æ˜?/title><link>http://www.aygfsteel.com/EricGu/archive/2010/12/14/340650.html</link><dc:creator>Eric Gu</dc:creator><author>Eric Gu</author><pubDate>Tue, 14 Dec 2010 07:31:00 GMT</pubDate><guid>http://www.aygfsteel.com/EricGu/archive/2010/12/14/340650.html</guid><wfw:comment>http://www.aygfsteel.com/EricGu/comments/340650.html</wfw:comment><comments>http://www.aygfsteel.com/EricGu/archive/2010/12/14/340650.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/EricGu/comments/commentRss/340650.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/EricGu/services/trackbacks/340650.html</trackback:ping><description><![CDATA[/**<br />  * <br />  * @author liuguangyi<br />  * @content  ejb3注解的API定义在javax.persistence.*包里面ã€?br />  * <br />  * 注释说明åQ?br />  * @Entity —â€?ž®†ä¸€ä¸ªç±»å£°æ˜Žä¸ÞZ¸€ä¸ªå®žä½“bean(即一个持久化POJO¾c?<br />  * @Id —â€?注解声明äº?ji¨£n)该实体bean的标识属性(对应表中的主键)(j¨ª)ã€?br />  * @Table —â€?注解声明äº?ji¨£n)该实体bean映射指定的表åQˆtableåQ?目录åQˆcatalogåQ‰å’Œschema的名å­?br />  * @Column —â€?注解声明äº?ji¨£n)属性到列的映射。该注解有如下的属æ€?br />  *  name  å¯é€‰ï¼Œåˆ—名åQˆé»˜è®¤å€¼æ˜¯å±žæ€§ååQ?br />  *  unique å¯é€‰ï¼Œæ˜¯å¦åœ¨è¯¥åˆ—上讄¡½®å”¯ä¸€¾U¦æŸåQˆé»˜è®¤å€¼falseåQ?br />  *  nullable 可选,是否讄¡½®è¯¥åˆ—çš„å€¼å¯ä»¥äØ“(f¨´)½Iºï¼ˆé»˜è®¤å€¼falseåQ?br />  *  insertable å¯é€‰ï¼Œè¯¥åˆ—æ˜¯å¦ä½œäØ“(f¨´)生成的insert语句中的一个列åQˆé»˜è®¤å€¼trueåQ?br />  *  updatable å¯é€‰ï¼Œè¯¥åˆ—æ˜¯å¦ä½œäØ“(f¨´)生成的update语句中的一个列åQˆé»˜è®¤å€¼trueåQ?br />  *  columnDefinition å¯é€‰ï¼Œä¸ø™¿™ä¸ªç‰¹å®šåˆ—覆盖sql ddl片段åQˆè¿™å¯èƒ½å¯ÆD‡´æ— æ³•在不同数据库间移植)(j¨ª)<br />  *  table å¯é€‰ï¼Œå®šä¹‰å¯¹åº”的表åQˆé»˜è®¤äØ“(f¨´)主表åQ?br />  *  length å¯é€‰ï¼Œåˆ—长度(默认å€?55åQ?br />  *  precision 可选,列十˜q›åˆ¶¾_‘Öº¦åQˆdecimal precision)(默认å€?åQ?br />  *  scale å¯é€‰ï¼Œå¦‚果列十˜q›åˆ¶æ•°å€ÆDŒƒå›ß_(d¨¢)¼ˆdecimal scaleåQ‰å¯ç”¨ï¼Œåœ¨æ­¤è®„¡½®åQˆé»˜è®¤å€?åQ?br />  * @GeneratedValue —â€?注解声明äº?ji¨£n)主键的生成½{–略。该注解有如下属æ€?br />  *  strategy 指定生成的策略(JPA定义的)(j¨ª)åQŒè¿™æ˜¯ä¸€ä¸ªGenerationType。默认是GenerationType. AUTO<br />  *   GenerationType.AUTO 主键ç”Þq¨‹åºæŽ§åˆ?br />  *   GenerationType.TABLE 使用一个特定的数据库表格来保存?sh¨´)¸»é”?br />  *   GenerationType.IDENTITY 主键由数据库自动生成åQˆä¸»è¦æ˜¯è‡ªåŠ¨å¢žé•¿¾cÕdž‹åQ?br />  *   GenerationType.SEQUENCE æ ÒŽ(gu¨©)®åº•层数据库的序列来生成主键,条äšg是数据库支持序列。(˜q™ä¸ªå€ÆD¦ä¸Žgenerator一起ä‹É用)(j¨ª)<br />  *  generator 指定生成主键使用的生成器åQˆå¯èƒ½æ˜¯orcale中的序列åQ‰ã€?br />  * @SequenceGenerator —â€?注解声明äº?ji¨£n)一个数据库序列。该注解有如下属æ€?br />  *  name è¡¨ç¤ºè¯¥è¡¨ä¸»é”®ç”Ÿæˆ½{–略名称åQŒå®ƒè¢«å¼•用在@GeneratedValue中设¾|®çš„“gernerator”å€ég¸­<br />  *  sequenceName 表示生成½{–略用到的数据库序列名称ã€?br />  *  initialValue 表示主键初始å€û|¼Œé»˜è®¤ä¸?.<br />  *  allocationSize 每次主键值增加的大小åQŒä¾‹å¦‚设¾|®æˆ1åQŒåˆ™è¡¨ç¤ºæ¯æ¬¡åˆ›å¾æ–°è®°å½•后自动åŠ?åQŒé»˜è®¤äØ“(f¨´)50.<br />  * @GenericGenerator —â€?注解声明äº?ji¨£n)一个hibernate的主键生成策略。支持十三种½{–略。该注解有如下属æ€?br />  *  name 指定生成器名¿U?br />  *  strategy 指定具体生成器的¾cÕdåQˆæŒ‡å®šç”Ÿæˆç­–略)(j¨ª)ã€?br />  *  parameters 得到strategy指定的具体生成器所用到的参数ã€?br />  *    其十三种½{–ç•¥åQˆstrategy属性的å€û|¼‰(j¨ª)如下åQ?br />  *   1.native 对于orcale采用Sequence方式åQŒå¯¹äºŽMySQLå’ŒSQL Server采用identity(处境主键生成机制)åQ?br />  *     nativež®±æ˜¯ž®†ä¸»é”®çš„生成工作ž®†ç”±æ•°æ®åº“完成,hibernate不管åQˆå¾ˆå¸¸ç”¨åQ?br />  *     例:(x¨¬)@GeneratedValue(generator = "paymentableGenerator")    <br />  *          @GenericGenerator(name = "paymentableGenerator", strategy = "native")<br />  *      2.uuid 采用128位的uuid½Ž—法生成主键åQŒuuidè¢«ç¼–ç äØ“(f¨´)一ä¸?2ä½?6˜q›åˆ¶æ•°å­—的字½W¦ä¸²ã€‚占用空间大åQˆå­—½W¦ä¸²¾cÕdž‹åQ‰ã€?br />  *       例:(x¨¬)@GeneratedValue(generator = "paymentableGenerator")    <br />  *          @GenericGenerator(name = "paymentableGenerator", strategy = "uuid")<br />  *      3.hilo 要在数据库中建立一张额外的表,默认表名为hibernate_unque_keyåQŒé»˜è®¤å­—ŒDµäØ“(f¨´)integer¾cÕdž‹åQŒå¿U°æ˜¯next_hiåQˆæ¯”较少用)(j¨ª)<br />  *       例:(x¨¬)@GeneratedValue(generator = "paymentableGenerator")    <br />  *          @GenericGenerator(name = "paymentableGenerator", strategy = "hilo")<br />  *      4.assigned 在插入数据的时候主键由½E‹åºå¤„理åQˆå¾ˆå¸¸ç”¨åQ‰ï¼Œ˜q™æ˜¯<generator>元素没有指定时的默认生成½{–略。等同于JPA中的AUTOã€?br />  *       例:(x¨¬)@GeneratedValue(generator = "paymentableGenerator")    <br />  *          @GenericGenerator(name = "paymentableGenerator", strategy = "assigned")<br />  *      5.identity 使用SQL Serverå’ŒMySQL的自增字ŒDµï¼Œ˜q™ä¸ªæ–ÒŽ(gu¨©)³•不能攑ֈ°Oracle中,Oracle不支持自增字ŒDµï¼Œè¦è®¾å®šsequence(MySQLå’ŒSQL Server中很常用)。等同于JPA中的IDENTITY<br />  *       例:(x¨¬)@GeneratedValue(generator = "paymentableGenerator")    <br />  *          @GenericGenerator(name = "paymentableGenerator", strategy = "identity")<br />  *      6.select 使用触发器生成主键(主要用于早期的数据库主键生成机制åQŒå°‘用)(j¨ª)<br />  *       例:(x¨¬)@GeneratedValue(generator = "paymentableGenerator")    <br />  *          @GenericGenerator(name = "paymentableGenerator", strategy = "select")<br />  *      7.sequence 调用谨慎数据库的序列来生成主键,要设定序列名åQŒä¸ç„¶hibernate无法扑ֈ°ã€?br />  *       例:(x¨¬)@GeneratedValue(generator = "paymentableGenerator")   <br />  *   @GenericGenerator(name = "paymentableGenerator", strategy = "sequence",    <br />  *    parameters = { @Parameter(name = "sequence", value = "seq_payablemoney") })<br />  *  8.seqhilo 通过hilo½Ž—法实现åQŒä½†æ˜¯ä¸»é”®åŽ†å²ä¿å­˜åœ¨Sequence中,适用于支持Sequence的数据库åQŒå¦‚Orcale(比较?y¨­u)®‘用åQ?<br />  *  ä¾‹ï¼š(x¨¬)@GeneratedValue(generator = "paymentableGenerator")   <br />  *    @GenericGenerator(name = "paymentableGenerator", strategy = "seqhilo",    <br />  *    parameters = { @Parameter(name = "max_lo", value = "5") })<br />  *  9.increnment 插入数据的时候hibernateä¼?x¨¬)给主键æ·ÕdŠ ä¸€ä¸ªè‡ªå¢žçš„ä¸»é”®åQŒä½†æ˜¯ä¸€ä¸ªhibernate实例ž®Þq»´æŠ¤ä¸€ä¸ªè®¡æ•°å™¨åQŒæ‰€ä»¥åœ¨å¤šä¸ªå®žä¾‹˜qè¡Œçš„æ—¶å€™ä¸èƒ½ä‹É用这个方法ã€?br />  *   例:(x¨¬)@GeneratedValue(generator = "paymentableGenerator")    <br />  *          @GenericGenerator(name = "paymentableGenerator", strategy = "increnment")<br />  *      10.foreign 使用另一个相关的对象的主键。通常å’?lt;on<wbr>e-to-on<wbr>e>联合èµäh¥ä½¿ç”¨ã€?br />  *      例:(x¨¬)@Id    <br />  *    @GeneratedValue(generator = "idGenerator")   <br />  *    @GenericGenerator(name = "idGenerator", strategy = "foreign",    <br />  *         parameters = { @Parameter(name = "property", value = "info") })    <br />  *    Integer id;<br />  *   @On<wbr>eToOne  <br />  *   EmployeeInfo info;<br />  *  11.guid 采用数据库底层的guid½Ž—法机制åQŒå¯¹åº”MySQLçš„uuid()函数åQŒSQL Serverçš„newid()函数åQŒORCALEçš„rawtohex(sys_guid())函数½{?br />  *  ä¾‹ï¼š(x¨¬)@GeneratedValue(generator = "paymentableGenerator")     <br />  *    @GenericGenerator(name = "paymentableGenerator", strategy = "guid") <br />  *  12.uuid.hex 看uudi,廸™®®ç”¨uuid替换<br />  *    例:(x¨¬)@GeneratedValue(generator = "paymentableGenerator")     <br />  *    @GenericGenerator(name = "paymentableGenerator", strategy = "uuid.hex")<br />  *  13.sequence-identity sequence½{–略的扩展,采用立即‹‚€(g¨¨)索策略来获取sequenceå€û|¼Œéœ€è¦JDBC3.0å’ŒJDK4以上åQˆå«1.4åQ‰ç‰ˆæœ?br />  *       例:(x¨¬)@GeneratedValue(generator = "paymentableGenerator")   <br />  *   @GenericGenerator(name = "paymentableGenerator", strategy = "sequence-identity",    <br />  *         parameters = { @Parameter(name = "sequence", value = "seq_payablemoney") })  <br />  *      <br />  * @On<wbr>eToOne 讄¡½®ä¸€å¯¹ä¸€ä¸ªå…³è”。cascade属性有五个å€?只有CascadeType.ALL好用åQŸå¾ˆå¥‡æ€?åQŒåˆ†åˆ«æ˜¯CascadeType.PERSIST(¾U§è”新徏)åQŒCascadeType.REMOVEåQˆçñ”联删除)(j¨ª)åQŒCascadeType.REFRESHåQˆçñ”联刷斎ͼ‰(j¨ª)åQŒCascadeType.MERGEåQˆçñ”联更斎ͼ‰(j¨ª)åQŒCascadeType.ALLåQˆå…¨éƒ¨å››™å¹ï¼‰(j¨ª)<br />  *    æ–ÒŽ(gu¨©)³•一<br />  *     ä¸»è¡¨åQ??@On<wbr>eToOne(cascade = CascadeType.ALL)<br />  *      @PrimaryKeyJoinColumn<br />  *      public 从表¾c?get从表¾c?){return 从表对象}<br />  *      从表åQšæ²¡æœ‰ä¸»è¡¨ç±»ã€?br />  *      注意åQšè¿™¿Uæ–¹æ³•要求主表与从表的主键值想对应ã€?br />  *   æ–ÒŽ(gu¨©)³•äº?br />  *      主表åQ?@On<wbr>eToOne(cascade = CascadeType.ALL)<br />  *          @JoinColumn(name="主表外键") //˜q™é‡ŒæŒ‡å®šçš„æ˜¯æ•°æ®åº“中的外键字ŒDüc(di¨£n)€?br />  *          public 从表¾c?get从表¾c?){return 从表¾c»}<br />  *      从表åQš@On<wbr>eToOne(mappedBy = "主表¾cÖM¸­çš„从表属æ€?)//例主表User中有一个从表属性是Heart¾cÕdž‹çš„heartåQŒè¿™é‡Œå°±å¡«heart<br />  *          public 主表¾c?get主表¾c?){return 主表对象}<br />  *      注意åQš@JoinColumn是可选的。默认值是从表变量å?"_"+从表的主键(注意åQŒè¿™é‡ŒåŠ çš„æ˜¯ä¸»é”®ã€‚è€Œä¸æ˜¯ä¸»é”®å¯¹åº”çš„å˜é‡åQ‰ã€?br />  * æ–ÒŽ(gu¨©)³•ä¸?br />  *      主表åQš@On<wbr>eToOne(cascade=CascadeType.ALL)<br />  *          @JoinTable( name="å…Œ™”表名",<br />  *    joinColumns = @JoinColumn(name="主表外键"),<br />  *    inverseJoinColumns = @JoinColumns(name="从表外键")<br />  *          )<br />  *      从表åQš@On<wbr>eToOne(mappedBy = "主表¾cÖM¸­çš„从表属æ€?)//例主表User中有一个从表属性是Heart¾cÕdž‹çš„heartåQŒè¿™é‡Œå°±å¡«heart<br />  *          public 主表¾c?get主表¾c?){return 主表对象}    <br />  *  @ManyToOne 讄¡½®å¤šå¯¹ä¸€å…Œ™”<br />  *    æ–ÒŽ(gu¨©)³•一       <br />  *    @ManyToOne(cascade={CasCadeType.PERSIST,CascadeType.MERGE})<br />  *    @JoinColumn(name="外键")<br />  *    public 主表¾c?get主表¾c?){return 主表对象}<br />  *    æ–ÒŽ(gu¨©)³•äº?br />  *    @ManyToOne(cascade={CascadeType.PERSIST,CascadeType.MERGE})<br />  *    @JoinTable(name="å…Œ™”表名"åQ?br />  *     joinColumns = @JoinColumn(name="主表外键"),<br />  *     inverseJoinColumns = @JoinColumns(name="从表外键")<br />  *    )<br />  *  @On<wbr>eToMany 讄¡½®ä¸€å¯¹å¤šå…Œ™”。cascade属性指定关联çñ”åˆ?参考@On<wbr>eToOne中的说明。fetch指定是否延迟加蝲åQŒå€égØ“(f¨´)FetchType.LAZY表示延迟åQŒäØ“(f¨´)FetchType.EAGER表示立即加蝲<br />  *    æ–ÒŽ(gu¨©)³•一     使用˜q™ç§é…ç½®åQŒåœ¨ä¸?#8220;一ç«?#8221;æ·ÕdŠ “多端”æ—Óž¼Œä¸ä¼š(x¨¬)修改“多端”的外键。在“一ç«?#8221;加蝲æ—Óž¼Œä¸ä¼š(x¨¬)得到“多端”。如果ä‹É用åšg˜qŸåŠ è½½ï¼Œåœ¨è¯»“多端”列表时会(x¨¬)出异常,立即加蝲在得到多端时åQŒæ˜¯ä¸€ä¸ªç©ºé›†åˆåQˆé›†åˆå…ƒç´ äØ“(f¨´)0åQ‰ã€?br />  *    “一ç«?#8221;配置<br />  *    @On<wbr>eToMany(mappedBy="“多端”的属æ€?)<br />  *    public List<“多端”¾c?gt; get“多端”列表(){return “多端”列表}<br />  *    “多端”配置参考@ManyToOne.     <br />  *    æ–ÒŽ(gu¨©)³•äº?br />  *    “一ç«?#8221;配置<br />  *    @On<wbr>eToMany(mappedBy="“多端”的属æ€?)<br />  *    @MapKey(name="“多端”åšäØ“(f¨´)Key的属æ€?)<br />  *    public Map<“多端”åšäØ“(f¨´)Key的属性的¾c?主表¾c?gt; get“多端”列表åQˆï¼‰(j¨ª){return “多端”列表}<br />  *    “多端”配置参考@ManyToOne. <br />  *    æ–ÒŽ(gu¨©)³•ä¸?使用˜q™ç§é…ç½®åQŒåœ¨ä¸?#8220;一ç«?#8221;æ·ÕdŠ “多端”æ—Óž¼Œå¯ä»¥ä¿®æ”¹“多端”的外键ã€?br />  *    “一ç«?#8221;配置<br />  *    @On<wbr>eToMany<br />  *    @JoinColumn(name="“多端”外键") <br />  *    public List<“多端”¾c?gt; get“多端”列表(){return “多端”列表}<br />  *    “多端”配置参考@ManyToOne.     <br />  *    <br />  *   <br />  */ <img src ="http://www.aygfsteel.com/EricGu/aggbug/340650.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/EricGu/" target="_blank">Eric Gu</a> 2010-12-14 15:31 <a href="http://www.aygfsteel.com/EricGu/archive/2010/12/14/340650.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java语法æ€È»“ - æ–ÒŽ(gu¨©)³•http://www.aygfsteel.com/EricGu/archive/2009/06/30/284798.htmlEric GuEric GuTue, 30 Jun 2009 09:17:00 GMThttp://www.aygfsteel.com/EricGu/archive/2009/06/30/284798.htmlhttp://www.aygfsteel.com/EricGu/comments/284798.htmlhttp://www.aygfsteel.com/EricGu/archive/2009/06/30/284798.html#Feedback0http://www.aygfsteel.com/EricGu/comments/commentRss/284798.htmlhttp://www.aygfsteel.com/EricGu/services/trackbacks/284798.html
1、重写只能出现在¾l§æ‰¿å…³ç³»ä¹‹ä¸­ã€‚当一个类¾l§æ‰¿å®ƒçš„父类æ–ÒŽ(gu¨©)³•æ—Óž¼Œéƒ½æœ‰æœÞZ¼š(x¨¬)重写该父¾cÈš„æ–ÒŽ(gu¨©)³•。一个特例是父类的方法被标识为final。重写的主要优点是能够定义某个子¾cÕdž‹ç‰ÒŽ(gu¨©)œ‰çš„行为ã€?br />     class Animal {
        public void eat(){
            System.out.println ("Animal is eating.");
        }
    }
    
    class Horse extends Animal{
        public void eat(){
            System.out.println ("Horse is eating.");
        }
    }

2、对于从父类¾l§æ‰¿æ¥çš„æŠ½è±¡æ–ÒŽ(gu¨©)³•åQŒè¦ä¹ˆåœ¨å­ç±»ç”¨é‡å†™çš„æ–¹å¼è®¾è®¡è¯¥æ–¹æ³•,要么把子¾cÖM¹Ÿæ ‡è¯†ä¸ºæŠ½è±¡çš„。所以抽象方法可以说是必™å»è¦è¢«é‡å†™çš„æ–ÒŽ(gu¨©)³•ã€?br />
3、重写的意义ã€?br /> 重写æ–ÒŽ(gu¨©)³•可以实现多态,用父¾cȝš„引用来操¾Uµå­¾cÕd¯¹è±¡ï¼Œä½†æ˜¯åœ¨å®žé™…运行中对象ž®†è¿è¡Œå…¶è‡ªå·±ç‰ÒŽ(gu¨©)œ‰çš„æ–¹æ³•ã€?br />     public class Test {
        public static void main (String[] args) {
            Animal h = new Horse();
            h.eat();    
        }
    }

    class Animal {
        public void eat(){
            System.out.println ("Animal is eating.");
        }
    }
    
    class Horse extends Animal{
        public void eat(){
            System.out.println ("Horse is eating.");
        }
        public void buck(){
        }
    }

一个原则是åQšä‹É用了(ji¨£n)什么引用,¾~–译器就ä¼?x¨¬)只调用引用¾cÀL‰€æ‹¥æœ‰çš„æ–¹æ³•。如果调用子¾cȝ‰¹æœ‰çš„æ–ÒŽ(gu¨©)³•åQŒå¦‚上例的h.buck(); ¾~–译器会(x¨¬)抱怨的。也ž®±æ˜¯è¯ß_(d¨¢)¼Œ¾~–译器只看引用类型,而不是对象类型ã€?br />
4、重写方法的规则ã€?br /> 若想实现一个合格重写方法,而不是重载,那么必须同时满èƒö下面的要求!

A、重写规则之一åQšé‡å†™æ–¹æ³•不能比被重写方法限制有更严格的讉K—®¾U§åˆ«ã€?br /> åQˆä½†æ˜¯å¯ä»¥æ›´òq¿æ³›åQŒæ¯”如父¾cÀL–¹æ³•是包访问权限,子类的重写方法是public讉K—®æƒé™ã€‚)(j¨ª)
比如åQšObject¾cÀLœ‰ä¸ªtoString()æ–ÒŽ(gu¨©)³•åQŒå¼€å§‹é‡å†™è¿™ä¸ªæ–¹æ³•的时候我们æ€Õd®¹æ˜“忘记public修饰½W¦ï¼Œ¾~–译器当然不ä¼?x¨¬)放˜q‡ä“Q何教训我们的æœÞZ¼š(x¨¬)。出错的原因ž®±æ˜¯åQšæ²¡æœ‰åŠ ä»ÖM½•讉K—®ä¿®é¥°½W¦çš„æ–ÒŽ(gu¨©)³•å…ähœ‰åŒ…访问权限,包访问权限比public当然要严æ égº†(ji¨£n)åQŒæ‰€ä»¥ç¼–译器ä¼?x¨¬)报错的ã€?br />
B、重写规则之二:(x¨¬)参数列表必须与被重写æ–ÒŽ(gu¨©)³•的相同ã€?br /> 重写有个孪生的弟弟叫重蝲åQŒä¹Ÿž®±æ˜¯åŽé¢è¦å‡ºåœºçš„。如果子¾cÀL–¹æ³•的参数与父¾cÕd¯¹åº”çš„æ–ÒŽ(gu¨©)³•不同åQŒé‚£ä¹ˆå°±æ˜¯ä½ è®¤é”™äºÞZº†(ji¨£n)åQŒé‚£æ˜¯é‡è½½ï¼Œä¸æ˜¯é‡å†™ã€?br />
C、重写规则之三:(x¨¬)˜q”回¾cÕdž‹å¿…须与被重写æ–ÒŽ(gu¨©)³•的返回类型相同ã€?br /> 父类æ–ÒŽ(gu¨©)³•AåQšvoid eat(){}  子类æ–ÒŽ(gu¨©)³•BåQšint eat(){}  两者虽然参数相同,可是˜q”回¾cÕdž‹ä¸åŒåQŒæ‰€ä»¥ä¸æ˜¯é‡å†™ã€?br /> 父类æ–ÒŽ(gu¨©)³•AåQšint eat(){}   子类æ–ÒŽ(gu¨©)³•BåQšlong eat(){}  ˜q”回¾cÕdž‹è™½ç„¶å…¼å®¹çˆ¶ç±»åQŒä½†æ˜¯ä¸åŒå°±æ˜¯ä¸åŒï¼Œæ‰€ä»¥ä¸æ˜¯é‡å†™ã€?br />
D、重写规则之四:(x¨¬)重写æ–ÒŽ(gu¨©)³•不能抛出新的异常或者比被重写方法声明的‹‚€(g¨¨)查异常更òq¿çš„‹‚€(g¨¨)查异常。但是可以抛出更ž®‘,更有限或者不抛出异常ã€?br />     import java.io.*;
    public class Test {
        public static void main (String[] args) {
            Animal h = new Horse();
            try {
                h.eat();    
            }
            catch (Exception e) {
            }
        }
    }

    class Animal {
        public void eat() throws Exception{
            System.out.println ("Animal is eating.");
            throw new Exception();
        }
    }
    
    class Horse extends Animal{
        public void eat() throws IOException{
            System.out.println ("Horse is eating.");
            throw new IOException();
        }
    }
˜q™ä¸ªä¾‹å­ä¸­ï¼Œçˆ¶ç±»æŠ›å‡ºäº?ji¨£n)检查异常ExceptionåQŒå­¾cÀLŠ›å‡ºçš„IOException是Exception的子¾c»ï¼Œä¹Ÿå³æ˜¯æ¯”被重写的æ–ÒŽ(gu¨©)³•抛出äº?ji¨£n)更有限的异常,˜q™æ˜¯å¯ä»¥çš„。如果反˜q‡æ¥åQŒçˆ¶¾cÀLŠ›å‡ºIOExceptionåQŒå­¾cÀLŠ›å‡ºæ›´ä¸ºå®½æ³›çš„ExceptionåQŒé‚£ä¹ˆä¸ä¼?x¨¬)通过¾~–译的ã€?br /> 注意åQšè¿™¿Ué™åˆ¶åªæ˜¯é’ˆå¯ÒŽ(gu¨©)£€æŸ¥å¼‚常,至于˜qè¡Œæ—¶å¼‚常RuntimeExceptionå?qi¨¢ng)其子类不再˜q™ä¸ªé™åˆ¶ä¹‹ä¸­ã€?br />
E、重写规则之五:(x¨¬)ä¸èƒ½é‡å†™è¢«æ ‡è¯†äØ“(f¨´)final的方法ã€?br />
F、重写规则之六:(x¨¬)如果一个方法不能被¾l§æ‰¿åQŒåˆ™ä¸èƒ½é‡å†™å®ƒã€?br /> 比较典型的就是父¾cȝš„privateæ–ÒŽ(gu¨©)³•。下例会(x¨¬)产生一个有­‘£çš„现象ã€?br />     public class Test {
        public static void main (String[] args) {
            //Animal h = new Horse();
            Horse h = new Horse();
            h.eat();
        }
    }

    class Animal {
        private void eat(){
            System.out.println ("Animal is eating.");
        }
    }
    
    class Horse extends Animal{
        public void eat(){
            System.out.println ("Horse is eating.");
        }
    }
˜q™æ®µä»£ç æ˜¯èƒ½é€šè¿‡¾~–译的。表面上看来˜qåäº?ji¨£n)第六条规则åQŒä½†å®žé™…上那是一点åéy合。Animal¾cȝš„eat()æ–ÒŽ(gu¨©)³•不能被ç‘ô承,因此Horse¾cÖM¸­çš„eat()æ–ÒŽ(gu¨©)³•是一个全新的æ–ÒŽ(gu¨©)³•åQŒä¸æ˜¯é‡å†™ä¹Ÿä¸æ˜¯é‡è²åQŒåªæ˜¯ä¸€ä¸ªåªå±žäºŽHorse¾cȝš„全新的方法!˜q™ç‚¹è®©å¾ˆå¤šäh˜qähƒ‘äº?ji¨£n),但是也不是那么难以理解ã€?br /> main()æ–ÒŽ(gu¨©)³•å¦‚æžœæ˜¯è¿™æ øP¼š(x¨¬)
    Animal h = new Horse();
    //Horse h = new Horse();
    h.eat();
¾~–译器会(x¨¬)报错åQŒäØ“(f¨´)什么呢åQŸHorse¾cȝš„eat()æ–ÒŽ(gu¨©)³•是public的啊åQåº”该可以调用啊åQè¯·ç‰¢è®°åQŒå¤šæ€åªçœ‹çˆ¶¾cÕd¼•用的æ–ÒŽ(gu¨©)³•åQŒè€Œä¸çœ‹å­¾cÕd¯¹è±¡çš„æ–ÒŽ(gu¨©)³•åQ?br />

二、方法的重蝲ã€?br /> 重蝲是有好的åQŒå®ƒä¸è¦æ±‚你在调用一个方法之前è{换数据类型,它会(x¨¬)自动地寻扑֌¹é…çš„æ–ÒŽ(gu¨©)³•。方法的重蝲是在¾~–译时刻ž®±å†³å®šè°ƒç”¨å“ªä¸ªæ–¹æ³•了(ji¨£n)åQŒå’Œé‡å†™ä¸åŒã€‚最最常用的地方就是构造器的重载ã€?br />
1、基本数据类型参数的重蝲ã€?br />     public class Test {
        static void method(byte b){
            System.out.println ("method:byte");
        }
        static void method(short s){
            System.out.println ("method:short");
        }
        static void method(int i){
            System.out.println ("method:int");
        }
        static void method(float f){
            System.out.println ("method:float");
        }
        static void method(double d){
            System.out.println ("method:double");
        }
        public static void main (String[] args) {
            method((byte)1);
            method('c');
            method(1);
            method(1L);
            method(1.1);
            method(1.1f);
        }
    }
输出¾l“æžœåQ?br /> method:byte
method:int
method:int
method:float
method:double
method:float

可以看出åQšé¦–先要å¯ÀL‰¾çš„æ˜¯æ•°æ®¾cÕdž‹æ­£å¥½åŒšw…æ–ÒŽ(gu¨©)³•。如果找不到åQŒé‚£ä¹ˆå°±æå‡ä¸ø™¡¨è¾¾èƒ½åŠ›æ›´å¼ºçš„æ•°æ®¾cÕdž‹åQŒå¦‚上例没有正好容纳long的整数类型,那么ž®Þp{æ¢äØ“(f¨´)float¾cÕdž‹çš„。如果通过提升也不能找到合适的兼容¾cÕdž‹åQŒé‚£ä¹ˆç¼–译器ž®×ƒ¼š(x¨¬)报错。反正是不会(x¨¬)è‡ªåŠ¨è½¬æ¢ä¸ø™¾ƒ?y¨­u)®çš„æ•°æ®¾cÕdž‹çš„,必须自己强制转换åQŒè‡ªå·±æ¥æ‰¿æ‹…转变后果ã€?br />
char¾cÕdž‹æ¯”较ç‰ÒŽ(gu¨©)®ŠåQŒå¦‚果找不到正好匚w…çš„类型,它会(x¨¬)转化为int而不是shortåQŒè™½ç„¶charæ˜?6位的ã€?br />

2、重载方法的规则�br />
A、被重蝲的方法必™åÀL”¹å˜å‚数列表ã€?br /> 参数必须不同åQŒè¿™æ˜¯æœ€é‡è¦çš„!不同有两个方面,参数的个敎ͼŒå‚数的类型,参数的顺序ã€?br />
B、被重蝲的方法与˜q”回¾cÕdž‹æ— å…³ã€?br /> 也就是说åQŒä¸èƒ½é€šè¿‡˜q”回¾cÕdž‹æ¥åŒºåˆ†é‡è½½æ–¹æ³•ã€?br />
C、被重蝲的方法可以改变访问修饰符ã€?br /> 没有重写æ–ÒŽ(gu¨©)³•那样严格的限制ã€?br />
D、被重蝲的方法可以声明新的或者更òq¿çš„‹‚€(g¨¨)查异常ã€?br /> 没有重写æ–ÒŽ(gu¨©)³•那样严格的限制ã€?br />
E、方法能够在一个类中或者在一个子¾cÖM¸­è¢«é‡è½½ã€?br />

3、带对象引用参数的方法重载ã€?br />     class Animal {}
    class Horse extends Animal{}
    
    public class Test {
        static void method(Animal a){
            System.out.println ("Animal is called.");
        }
        static void method(Horse h){
            System.out.println ("Horse is called.");
        }
        public static void main (String[] args) {
            Animal a = new Animal();
            Horse h = new Horse();
            Animal ah = new Horse();
            
            method(a);
            method(h);
            method(ah);
        }
    }
输出¾l“果是:(x¨¬)
Animal is called.
Horse is called.
Animal is called.
前两个输出没有ä“Q何问题。第三个æ–ÒŽ(gu¨©)³•ä¸ÞZ»€ä¹ˆä¸æ˜¯è¾“å‡?#8220;Horse is called.”呢?˜q˜æ˜¯é‚£å¥è€è¯åQŒè¦çœ‹å¼•用类型而不是对象类型,æ–ÒŽ(gu¨©)³•重蝲是在¾~–译时刻ž®±å†³å®šçš„äº?ji¨£n),引用¾cÕdž‹å†›_®šäº?ji¨£n)调用哪个版本的重蝲æ–Ò?gu¨©)³•ã€?br />

4、重载和重写æ–ÒŽ(gu¨©)³•区别的小¾l“ã€?br /> å¦‚æžœèƒ½å½»åº•å¼„æ˜Žç™½ä¸‹é¢çš„ä¾‹å­ï¼Œè¯´æ˜Žä½ å¯¹é‡è²å’Œé‡å†™éžå¸æ€º†(ji¨£n)解了(ji¨£n)åQŒå¯ä»¥ç»“束这节的复习(f¨¤n)äº?ji¨£n)ã€?br />     class Animal {
        public void eat(){
            System.out.println ("Animal is eating.");    
        }
    }
    class Horse extends Animal{
        public void eat(){
            System.out.println ("Horse is eating.");    
        }
        public void eat(String food){
            System.out.println ("Horse is eating " + food);
        }
    }
    
    public class Test {
        public static void main (String[] args) {
            Animal a = new Animal();
            Horse h = new Horse();
            Animal ah = new Horse();
            
            a.eat();
            h.eat();
            h.eat("apple");
            ah.eat();
            //a.eat("apple");
            //ah.eat("apple");
        }
    }

四个输出分别是什么?被注释的两条语句ä¸ÞZ»€ä¹ˆä¸èƒ½é€šè¿‡¾~–译åQ?br /> ½W¬ä¸€æ¡ï¼š(x¨¬)a.eat(); 普通的æ–ÒŽ(gu¨©)³•调用åQŒæ²¡æœ‰å¤šæ€ï¼Œæ²¡ä»€ä¹ˆæŠ€æœ¯å«é‡ã€‚调用了(ji¨£n)Animal¾cȝš„eat()æ–ÒŽ(gu¨©)³•åQŒè¾“出:(x¨¬)Animal is eating.
½W¬äºŒæ¡ï¼š(x¨¬)h.eat(); 普通的æ–ÒŽ(gu¨©)³•调用åQŒä¹Ÿæ²¡ä»€ä¹ˆæŠ€æœ¯å«é‡ã€‚调用了(ji¨£n)Horse¾cȝš„eat()æ–ÒŽ(gu¨©)³•åQŒè¾“出:(x¨¬)Horse is eating.
½W¬ä¸‰æ¡ï¼š(x¨¬)h.eat("apple"); 重蝲。Horse¾cȝš„两个eat()æ–ÒŽ(gu¨©)³•重蝲。调用了(ji¨£n)Horse¾cȝš„eat(String food)æ–ÒŽ(gu¨©)³•åQŒè¾“出:(x¨¬)Horse is eating apple
½W¬å››æ¡ï¼š(x¨¬)ah.eat(); 多态。前面有例子äº?ji¨£n),不难理解。输出:(x¨¬)Horse is eating.
½W¬äº”条:(x¨¬)a.eat("apple"); 低çñ”的错误,Animal¾cÖM¸­æ²¡æœ‰eat(String food)æ–ÒŽ(gu¨©)³•。因此不能通过¾~–译ã€?br /> ½W¬å…­æ¡ï¼š(x¨¬)ah.eat("apple"); 关键点就在这里。解决的æ–ÒŽ(gu¨©)³•˜q˜æ˜¯é‚£å¥è€è¯åQŒä¸èƒ½çœ‹å¯¹è±¡¾cÕdž‹åQŒè¦çœ‹å¼•用类型。Animal¾cÖM¸­æ²¡æœ‰eat(String food)æ–ÒŽ(gu¨©)³•。因此不能通过¾~–译ã€?br />
ž®ç»“一下:(x¨¬)多态不军_®šè°ƒç”¨å“ªä¸ªé‡è²ç‰ˆæœ¬åQ›å¤šæ€åªæœ‰åœ¨å†›_®šå“ªä¸ªé‡å†™ç‰ˆæœ¬æ—¶æ‰èµ·ä½œç”¨ã€?br /> 重蝲对应¾~–译æ—Óž¼Œé‡å†™å¯¹åº”˜qè¡Œæ—¶ã€‚够½Ž€‹zçš„äº?ji¨£n)吧åQ?br />

三、构造方法ã€?br /> 构造方法是一¿Uç‰¹ŒDŠçš„æ–ÒŽ(gu¨©)³•åQŒæ²¡æœ‰æž„造方法就不能创徏一个新对象。实际上åQŒä¸ä»…要调用对象实际¾cÕdž‹çš„æž„造方法,˜q˜è¦è°ƒç”¨å…¶çˆ¶¾cÈš„æž„造方法,向上˜q½æº¯åQŒç›´åˆ°Object¾c…R€‚构造方法不必显式地调用åQŒå½“使用new关键字时åQŒç›¸åº”的构造方法会(x¨¬)自动被调用ã€?br />
1、构造方法的规则ã€?br /> A、构造方法能使用ä»ÖM½•讉K—®ä¿®é¥°½W¦ã€‚包括privateåQŒäº‹å®žä¸Šjava¾cÕdº“有很多都是这æ ïL(f¨¥ng)š„åQŒè®¾è®¡è€…ä¸å¸Œæœ›ä½¿ç”¨è€…åˆ›å»ø™¯¥¾cȝš„对象ã€?br />
B、构造方法的名称必须与类名相同。这样ä‹É得构造方法与众不同,如果我们遵守sun的编码规范,ä¼ég¹Žåªæœ‰æž„造方法的首字母是大写的ã€?br />
C、构造方法不能有˜q”回¾cÕdž‹ã€?br /> 反过来说åQŒæœ‰˜q”回¾cÕdž‹çš„不是构造方æ³?br />     public class Test {
        int Test(){
            return 1;
        }
    }
˜q™ä¸ªæ–ÒŽ(gu¨©)³•是什么东西?一个冒充李é€ëŠš„李鬼而已åQŒint Test()和其他ä“Qä½•æ™®é€šæ–¹æ³•æ²¡ä»€ä¹ˆä¸¤æ øP¼Œž®±æ˜¯æ™®é€šçš„æ–ÒŽ(gu¨©)³•åQåªä¸è¿‡çœ‹è“v来很恶心(j¨©)åQŒç±»ä¼¼æ¶å¿?j¨©)的东西在考试卷子里比较多ã€?br />
Dã€å¦‚æžœä¸åœ¨ç±»ä¸­åˆ›å»ø™‡ªå·Þqš„æž„造方法,¾~–译器会(x¨¬)自动生成默认的不带参数的构造函数ã€?br /> ˜q™ç‚¹å¾ˆå®¹æ˜“验证!写一个这æ ïL(f¨¥ng)®€å•çš„¾c»ï¼Œ¾~–译ã€?br /> class Test {
}
对生成的Test.classæ–‡äšg反编译:(x¨¬)javap TeståQŒå¯ä»¥çœ‹åˆŽÍ¼š(x¨¬)
D:"JavaCode"bin>javap Test
Compiled from "Test.java"
class Test extends java.lang.Object{
    Test();
}
看到¾~–译器自动添加的默认构造函æ•îCº†(ji¨£n)吧!

E、如果只创徏äº?ji¨£n)带参数的构造方法,那么¾~–译器不ä¼?x¨¬)自动添加无参的构造方法的åQ?br />
F、在每个构造方法中åQŒå¦‚æžœä‹É用了(ji¨£n)重蝲构造函数this()æ–ÒŽ(gu¨©)³•åQŒæˆ–者父¾cÈš„æž„造方法super()æ–ÒŽ(gu¨©)³•åQŒé‚£ä¹ˆthis()æ–ÒŽ(gu¨©)³•或者super()æ–ÒŽ(gu¨©)³•必须攑֜¨½W¬ä¸€è¡Œã€‚而且˜q™ä¸¤ä¸ªæ–¹æ³•只能选择一个,因此它们之间没有™åºåºé—®é¢˜ã€?br />
G、除äº?ji¨£n)编译器生成的构造方法,而且没有昑ּåœ°è°ƒç”¨super()æ–ÒŽ(gu¨©)³•åQŒé‚£ä¹ˆç¼–译器ä¼?x¨¬)插入一个super()无参调用ã€?br />
H、抽象类有构造方法�br />

四、静(r¨´n)态方法的重蝲与重写(覆盖åQ‰ã€?br />
1、静(r¨´n)态方法是不能被覆盖的。可以分两种情况讨论åQ?br />
A、子¾cȝš„非静(r¨´n)态方æ³?#8220;覆盖”父类的静(r¨´n)态方法ã€?br /> ˜q™ç§æƒ…况下,是不能通过¾~–译的ã€?br />
class Father{
    
static void print(){
        System.out.println (
"in father  method");
    }
}
class Child extends Father{
    
void print(){
        System.out.println (
"in child method");
    }
}

staticæ–ÒŽ(gu¨©)³•表示该方法不兌™”具体的类的对象,可以通过¾cÕdç›´æŽ¥è°ƒç”¨åQŒä¹Ÿž®±æ˜¯¾~–译的前期就¾l‘定äº?ji¨£n),不存在后期动态绑定,也就是不能实现多态。子¾cȝš„非静(r¨´n)态方法是与具体的对象¾l‘定的,两者有着不同的含义ã€?br />
B、子¾cȝš„é?r¨´n)态方æ³?#8220;覆盖”父类é?r¨´n)态方法ã€?br /> ˜q™ä¸ªè¦†ç›–依然是带引号的。事实上把上面那个例子Child¾cȝš„printæ–ÒŽ(gu¨©)³•前面加上static修饰½W¦ï¼Œ¼‹®å®žèƒ½é€šè¿‡¾~–译åQä½†æ˜¯ä¸è¦ä»¥ä¸ø™¿™ž®±æ˜¯å¤šæ€ï¼å¤šæ€çš„特点是动态绑定,看下面的例子åQ?br />
class Father{
    
static void print(){
        System.out.println (
"in father  method");
    }
}
class Child extends Father{
    
static void print(){
        System.out.println (
"in child method");
    }
}

class Test{
    
public static void main (String[] args) {
        Father f 
=new Child();
        f.print();
    }
}

输出¾l“果是:(x¨¬)in father  method
从这个结果可以看出,òq¶æ²¡æœ‰å®žçŽ°å¤šæ€ã€?br /> 但是˜q™ç§å½¢å¼å¾ˆè¿·æƒ‘ähåQŒè²Œä¼¼å¤šæ€ï¼Œå®žé™…¾~–程中千万不要这æ ähžåQŒä¼š(x¨¬)把大家搞æ‡ëŠš„åQ?br /> 它不½W¦åˆè¦†ç›–表现出来的特性,不应该算是覆盖!
总而言之,é?r¨´n)态方法不能被覆盖ã€?br />
2、静(r¨´n)态方法可以和非静(r¨´n)态方法一栯‚¢«é‡è²ã€?br /> ˜q™æ ·çš„例子太多了(ji¨£n)åQŒæˆ‘不想写例½E‹äº†(ji¨£n)。看看java¾cÕdº“中很多这æ ïL(f¨¥ng)š„例子ã€?br /> 如java.util.Arrays¾cȝš„一堆重载的binarySearchæ–ÒŽ(gu¨©)³•ã€?br /> åœ¨è¿™é‡Œæä¸€ä¸‹æ˜¯å› äØ“(f¨´)查资料时看到˜q™æ ·çš„话“sunçš„SL275评¡¨‹è¯ß_(d¨¢)¼Œé?r¨´n)态方法只能控刉™™(r¨´n)态变量(他们本èín没有åQ‰ï¼Œé?r¨´n)态方法不能被重蝲和覆ç›?#8230;…”
å¤§å®¶ä¸è¦ç›æ€¿¡å•Šï¼å¯ä»¥é‡è²çš„。而且é?r¨´n)态与非静(r¨´n)态方法可以重载ã€?br />
从重载的机制很容易就理解äº?ji¨£n),重蝲是在¾~–译时刻ž®±å†³å®šçš„äº?ji¨£n),非é?r¨´n)态方法都可以åQŒé™(r¨´n)态方法怎么可能不会(x¨¬)呢?


]]>
Java语法æ€È»“ - 字符ä¸?/title><link>http://www.aygfsteel.com/EricGu/archive/2009/06/30/284780.html</link><dc:creator>Eric Gu</dc:creator><author>Eric Gu</author><pubDate>Tue, 30 Jun 2009 07:34:00 GMT</pubDate><guid>http://www.aygfsteel.com/EricGu/archive/2009/06/30/284780.html</guid><wfw:comment>http://www.aygfsteel.com/EricGu/comments/284780.html</wfw:comment><comments>http://www.aygfsteel.com/EricGu/archive/2009/06/30/284780.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/EricGu/comments/commentRss/284780.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/EricGu/services/trackbacks/284780.html</trackback:ping><description><![CDATA[Javaçš„String太特别了(ji¨£n)åQŒä¹Ÿå¤ªå¸¸ç”¨äº†(ji¨£n)åQŒæ‰€ä»¥é‡è¦ã€‚我初学Javaž®Þp¢«å®ƒæžè’™äº†(ji¨£n)åQŒå¤ªå¤šæØœæ·†çš„æ¦‚念äº?ji¨£n),比如它的不变性。所以必™åÀL·±å…¥æœºåˆ¶åœ°åŽÈ†è§£å®ƒã€?br /> <br /> <br /> 1、String中的每个字符都是一ä¸?6位的Unicode字符åQŒç”¨Unicode很容易表达丰富的国际化字½W¦é›†åQŒæ¯”如很好的中文支持。甚至Java的标识符都可以用汉字åQŒä½†æ˜¯æ²¡äºÞZ¼š(x¨¬)用吧åQˆåªåœ¨ä¸€æœ¬æ¸…华的《Java2实用教程》看˜q‡ï¼‰(j¨ª)ã€?br /> <br /> 2、判断空字符丌Ӏ‚根据需要自己选择某个或者它们的¾l„合<br />     if ( s == null )    //从引用的角度<br />     if ( s.length() == 0 )     //从长度判åˆ?br />     if ( s.trim().length () == 0 )     //是否有多个空白字½W?br /> trim()æ–ÒŽ(gu¨©)³•的作用是是移除前导和ž®ùNƒ¨çš„Unicode值小äº?"u0020'的字½W¦ï¼Œòq¶è¿”å›?#8220;修剪”好的字符丌Ӏ‚è¿™¿Uæ–¹æ³•很常用åQŒæ¯”如需要用戯‚¾“入用户名åQŒç”¨æˆ·ä¸ž®å¿ƒ(j¨©)加了(ji¨£n)前导或者尾部空æ û|¼Œä¸€ä¸ªå¥½çš„程序应该知道用户不是故意的åQŒå³ä½¿æ˜¯æ•…æ„çš„ä¹Ÿåº”è¯¥æ™ø™ƒ½ç‚¹åœ°å¤„理ã€?br /> 判断½IÞZ¸²æ˜¯å¾ˆå¸¸ç”¨çš„æ“ä½œï¼Œä½†æ˜¯Java¾cÕdº“直到1.6才提供了(ji¨£n)isEmpty()æ–ÒŽ(gu¨©)³•。当且仅å½?length() ä¸?0 æ—¶è¿”å›?trueã€?br /> <br /> 3、未初始化、空ä¸?"与null。它们是不同的概å¿üc(di¨£n)€‚对未初始化的对象操作会(x¨¬)被编译器挡在门外åQ›null是一个特ŒDŠçš„初始化å€û|¼Œæ˜¯ä¸€ä¸ªä¸æŒ‡å‘ä»ÖM½•å¯¹è±¡çš„å¼•ç”¨ï¼Œå¯¹å¼•ç”¨äØ“(f¨´)null的对象操作会(x¨¬)在运行时抛出异常NullPointerExceptionåQ›è€Œç©ºä¸²æ˜¯é•¿åº¦ä¸?的字½W¦ä¸²åQŒå’Œåˆ«çš„字符串的唯一区别ž®±æ˜¯é•¿åº¦ä¸?ã€?br /> 例子åQ?br />     public class StringTest{<br />         static String s1;<br />         public static void main(String[] args) {<br />             String s2;<br />             String s3 = "";<br />             System.out.print(s1.isEmpty());     //˜qè¡Œæ—¶å¼‚å¸?br />             System.out.print(s2.isEmpty());     //¾~–译出错<br />             System.out.print(s3.isEmpty());     //okåQè¾“出true<br />         }<br />     }<br /> <br /> 4、String¾cÈš„æ–ÒŽ(gu¨©)³•很多åQŒåœ¨¾~–写相关代码的时候看看JDK文档时有好处的,要不然花äº?ji¨£n)大量时间实çŽîC¸€ä¸ªå·²¾lå­˜åœ¨çš„æ–ÒŽ(gu¨©)³•æ˜¯å¾ˆä¸å€¼å¾—çš„ï¼Œå› äØ“(f¨´)¾~–写、测试、维护自å·Þqš„代码佉K¡¹ç›®çš„æˆæœ¬å¢žåŠ åQŒåˆ©æ¶¦å‡ž®‘,严重的话ä¼?x¨¬)导致开不出工资……<br /> <br /> 5、字½W¦ä¸²çš„æ¯”较ã€?br /> Java不允许自定义操作½W¦é‡è½½ï¼Œå› æ­¤å­—符串的比较要用compareTo() 或è€?compareToIgnoreCase()。s1.compareTo(s2)åQŒè¿”回值大äº?则,则前者大åQ›ç­‰äº?åQŒä¸€èˆ¬å¤§åQ›å°äº?åQŒåŽè€…大。比较的依据是字½W¦ä¸²ä¸­å„个字½W¦çš„Unicode倹{€?br /> <br /> 6、toString()æ–ÒŽ(gu¨©)³•ã€?br /> Javaçš„ä“Q何对象都有toString()æ–ÒŽ(gu¨©)³•åQŒæ˜¯ä»ŽObject对象¾l§æ‰¿è€Œæ¥çš„。它的作用就是让对象在输出时看è“v来更有意义,而不是奇怪的对象的内存地址。对‹¹‹è¯•也是很有帮助的ã€?br /> <br /> 7、String对象是不变的åQå¯ä»¥å˜åŒ–的是String对象的引用ã€?br /> String name = "ray";<br /> name.concat("long");  //字符串连æŽ?br /> System.out.println(name); //输出nameåQŒokåQŒè¿˜æ˜?ray"<br /> name = name.concat("long");  //把字½W¦ä¸²å¯¹è±¡˜qžæŽ¥çš„结果赋¾l™äº†(ji¨£n)name引用<br /> System.out.println(name);  //输出nameåQŒohåQï¼Œå˜æˆäº?raylong"<br /> 上述三条语句其实产生äº?个String对象åQ?ray"åQ?long"åQ?raylong"。第2条语句确实äñ”生了(ji¨£n)"raylong"字符ä¸ÔŒ¼Œä½†æ˜¯æ²¡æœ‰æŒ‡å®šæŠŠè¯¥å­—符串的引用赋给谁,因此没有改变name引用。第3条语句根据不变性,òq¶æ²¡æœ‰æ”¹å?ray"åQŒJVM创徏äº?ji¨£n)一个新的对象,æŠ?ray"åQ?long"的连接赋¾l™äº†(ji¨£n)name引用åQŒå› æ­¤å¼•用变?sh¨´)º†(ji¨£n),但是原对象没变ã€?br /> <br /> 8、String的不变性的机制昄¡„¶ä¼?x¨¬)在String帔R‡å†…有大量的冗余。如åQ?1" + "2" + "3" +......+ "n" 产生äº?ji¨£n)n+(n+1)个String对象åQå› æ­¤Javaä¸ÞZº†(ji¨£n)更有效地使用内存åQŒJVM留出一块特ŒDŠçš„内存区域åQŒè¢«¿UîCØ“(f¨´)“String帔R‡æ±?#8221;。对String多么照顾啊!当编译器遇见String帔R‡çš„æ—¶å€™ï¼Œå®ƒæ£€æŸ¥è¯¥æ± å†…是否已经存在相同的String帔R‡ã€‚如果找刎ͼŒž®±æŠŠæ–°å¸¸é‡çš„引用指向现有的StringåQŒä¸åˆ›å¾ä»ÖM½•æ–°çš„String帔R‡å¯¹è±¡ã€?br /> <br /> 那么ž®±å¯èƒ½å‡ºçŽ°å¤šä¸ªå¼•ç”¨æŒ‡å‘åŒä¸€ä¸ªString帔R‡åQŒä¼š(x¨¬)不会(x¨¬)有别名的危险呢?No problemåQString对象的不变性可以保证不ä¼?x¨¬)出现别名问题!˜q™æ˜¯String对象与普通对象的一点区别ã€?br /> <br /> 乍看èµäh¥˜q™æ˜¯åº•层的机åˆÓž¼Œå¯ÒŽ(gu¨©)ˆ‘们编½E‹æ²¡ä»€ä¹ˆåª„(ji¨£ng)响。而且˜q™ç§æœºåˆ¶ä¼?x¨¬)大òq…度提高String的效率,实际上却不是˜q™æ ·ã€‚䨓(f¨´)˜qžæŽ¥n个字½W¦ä¸²ä½¿ç”¨å­—符串连接操作时åQŒè¦æ¶ˆè€—的旉™—´æ˜¯nçš„åã^æ–¹çñ”åQå› ä¸ºæ¯ä¸¤ä¸ªå­—符串连接,它们的内定wƒ½è¦è¢«å¤åˆ¶ã€‚因此在处理大量的字½W¦ä¸²˜qžæŽ¥æ—Óž¼Œè€Œä¸”要求性能æ—Óž¼Œæˆ‘们不要用StringåQŒStringBuffer是更好的选择ã€?br /> <br /> 8、StringBuffer¾c…R€‚StringBuffer¾cÀL˜¯å¯å˜çš„,不会(x¨¬)在字½W¦ä¸²å¸”R‡æ± ä¸­åQŒè€Œæ˜¯åœ¨å †ä¸­ï¼Œä¸ä¼š(x¨¬)留下一大堆无用的对象。而且它可ž®†å­—½W¦ä¸²¾~“冲区安全地用于多个¾U¿ç¨‹ã€‚每个StringBuffer对象都有一定的定w‡ã€‚只要StringBuffer对象所包含的字½W¦åºåˆ—的长度没有­‘…出此容量,ž®±æ— éœ€åˆ†é…æ–°çš„内部¾~“冲区数¾l„。如果内部缓冲区溢出åQŒåˆ™æ­¤å®¹é‡è‡ªåŠ¨å¢žå¤§ã€‚è¿™ä¸ªå›ºå®šçš„å®šw‡æ˜?6个字½W¦ã€‚我¾l™è¿™¿Uç®—法è“v个名字叫“添饭½Ž—法”。先¾l™ä½ ä¸€æ»¡ç¢—饭,不够äº?ji¨£n)再¾l™ä½ ä¸€æ»¡ç¢—饭ã€?br /> 例子åQ?br />     StringBuffer sb = new StringBuffer();    //初始定w‡ä¸?16 个字½W?br />     sb.append("1234");    //˜q™æ˜¯4个字½W¦ï¼Œé‚£ä¹ˆ16个字½W¦çš„定w‡ž®Þpƒö够了(ji¨£n)åQŒæ²¡æœ‰æº¢å‡?br />     System.out.println(sb.length());    //输出字符串长度是4<br />     System.out.println(sb.capacity());    //输出该字½W¦ä¸²¾~“冲区的定w‡æ˜?6<br /> <br />     sb.append("12345678901234567");        //˜q™æ˜¯17个字½W¦ï¼Œ16个字½W¦çš„定w‡ä¸å¤Ÿäº?ji¨£n),扩容ä?7+16个字½W¦çš„定w‡<br />     System.out.println(sb.length());    //输出字符串长度是17<br />     System.out.println(sb.capacity());    //输出该字½W¦ä¸²¾~“冲区的定w‡æ˜?4<br /> <br />     sb.append("890").reverse().insert(10,"-");    <br />     System.out.println(sb);        //输出0987654321-09876543214321<br /> <br /> 字符串的长度和字½W¦ç¼“冲区的容量是两个概念åQŒæ³¨æ„åŒºåˆ«ã€?br /> ˜q˜æœ‰ä¸²è”的方式看èµäh¥æ˜¯ä¸æ˜¯å¾ˆé…øP¼ç”¨è¿”å›žå€ÆD¿žæŽ¥è“v来可以实现这¿Uç®€‹zå’Œä¼˜é›…ã€?br /> <br /> 10、StringBuilder¾c…R€?从J2SE 5.0 提供äº?ji¨£n)StringBuilder¾c»ï¼Œå®ƒå’ŒStringBuffer¾cÀL˜¯å­ªç”Ÿå…„弟åQŒå¾ˆåƒã€‚它存在的ä­h(hu¨¢n)值在于:(x¨¬)对字½W¦ä¸²æ“ä½œçš„æ•ˆçŽ‡æ›´é«˜ã€‚ä¸­‘³çš„æ˜¯çº¿½E‹å®‰å…¨æ— æ³•保证,不保证同步。那么两者性能到底差多ž®‘å‘¢åQŸå¾ˆå¤šï¼<br /> 请参阅:(x¨¬)http://book.csdn.net/bookfiles/135/1001354628.shtml<br /> 实践åQ?br /> 单个¾U¿ç¨‹çš„æ—¶å€™ä‹É用StringBuilder¾c»ï¼Œä»¥æé«˜æ•ˆçŽ‡ï¼Œè€Œä¸”å®ƒçš„APIå’ŒStringBuffer兼容åQŒä¸éœ€è¦é¢å¤–的学习(f¨¤n)成本åQŒç‰©¾ŸŽä­h(hu¨¢n)廉。多¾U¿ç¨‹æ—¶ä‹É用StringBufferåQŒä»¥ä¿è¯å®‰å…¨ã€?br /> <br /> 11、字½W¦ä¸²çš„æ¯”较ã€?br /> 下面˜q™æ¡å¯èƒ½ä¼?x¨¬)让你晕åQŒæ‰€ä»¥ä½ å¯ä»¥é€‰æ‹©çœ‹æˆ–者不看。它不会(x¨¬)对你的职业生涯造成ä»ÖM½•影响。而且谨记一条,比较字符串要用equals()ž®±okäº?ji¨£n)!一旦用äº?#8220;==”ž®×ƒ¼š(x¨¬)出现很怪异的现象。之所以把˜q™éƒ¨åˆ†æ”¾åœ¨æœ€åŽï¼Œæ˜¯æƒ³èŠ‚çœå¤§å®¶çš„æ—¶é—ß_(d¨¢)¼Œå› äØ“(f¨´)˜q™æ¡åˆè‡­åˆé•¿ã€‚推荐三¿UähåQšä¸€ã€æ²¡äº‹é—²ç€åž‹ã€‚二、想深入地理解Java的字½W¦ä¸²åQŒå³ä½¿æ˜Žæ˜ŽçŸ¥é“å­¦äº?ji¨£n)也没用。三、和我一æ ïL(f¨¥ng)ˆ±å¥½ç ”½I?#8220;èŒ?#8221;字有几种写法ã€?br /> <br /> ˜q˜æ˜¯é‚£å¥è€è¯åQŒString太特ŒDŠäº†(ji¨£n)åQŒä»¥è‡³äºŽæŸäº›è§„则对String不è“v作用。个人感觉这¿Uç‰¹ŒDŠæ€§åƈ不好。看例子åQ?br /> 例子AåQ?br />     String str1 = "java";<br />     String str2 = "java";<br />     System.out.print(str1==str2);<br /> 地球上有点Java基础的äh都知道会(x¨¬)输出falseåQŒå› ä¸?=比较的是引用åQŒequals比较的是内容。不是我忽æ?zh¨¨n) å¤§å®¶åQŒä½ ä»¬å¯ä»¥åœ¨è‡ªå·±çš„æœºå­ä¸Š˜qè¡Œä¸€ä¸‹ï¼Œ¾l“果是trueåQåŽŸå› å¾ˆ½Ž€å•,String对象被放˜q›å¸¸é‡æ± é‡Œäº†(ji¨£n)åQŒå†‹Æ¡å‡ºçŽ?#8220;java”字符串的时候,JVM很兴奋地把str2的引用也指向äº?#8220;java”对象åQŒå®ƒè®¤äØ“(f¨´)自己节省äº?ji¨£n)内存开销。不隄¡†è§£å§ 呵呵<br /> 例子BåQ?br />     String str1 = new String("java");<br />     String str2 = new String("java");<br />     System.out.print(str1==str2);<br /> 看过上例的都学聪明了(ji¨£n)åQŒè¿™‹Æ¡è‚¯å®šä¼š(x¨¬)输出trueåQå¾ˆä¸å¹¸åQŒJVMòq¶æ²¡æœ‰è¿™ä¹ˆåšåQŒç»“果是false。原因很½Ž€å•,例子A中é‚£¿Uå£°æ˜Žçš„æ–¹å¼¼‹®å®žæ˜¯åœ¨String帔R‡æ± åˆ›å»?#8220;java”对象åQŒä½†æ˜¯ä¸€æ—¦çœ‹åˆ°new关键字,JVMä¼?x¨¬)在堆中为String分配½Iºé—´ã€‚两者声明方式貌合神¼›»ï¼Œ˜q™ä¹Ÿæ˜¯æˆ‘æŠ?#8220;如何创徏字符串对è±?#8221;攑ֈ°åŽé¢æ¥è®²çš„原因。大家要沉住气,˜q˜æœ‰ä¸€ä¸ªä¾‹å­ã€?br /> 例子CåQ?br />     String str1 = "java";<br />     String str2 = "blog";<br />     String s = str1+str2;<br />     System.out.print(s=="javablog");<br /> 再看˜q™ä¸ªä¾‹å­åQŒå¾ˆå¤šåŒå¿—不敢妄­a€æ˜¯true˜q˜æ˜¯falseäº?ji¨£n)吧。爱玩脑½{‹æ€¥è{弯的äºÞZ¼š(x¨¬)说是falseå?#8230;…恭喜你,你会(x¨¬)抢答äº?ji¨£n)!把那ä?#8220;å?#8221;字去掉你ž®±å®Œå…¨æ­£¼‹®ã€‚原因很½Ž€å•,JVM¼‹®å®žä¼?x¨¬)对型如String str1 = "java"; çš„String对象攑֜¨å­—符串常量池里,但是它是在编译时刻那么做的,而String s = str1+str2; 是在˜qè¡Œæ—¶åˆ»æ‰èƒ½çŸ¥é“åQˆæˆ‘们当然一眼就看穿äº?ji¨£n),可是Java必须在运行时才知道的åQŒähè„‘å’Œç”?sh¨´)脑的结构不同ï¼?j¨ª)åQŒä¹Ÿž®±æ˜¯è¯´str1+str2是在堆里创徏的,s引用当然不可能指向字½W¦ä¸²å¸”R‡æ± é‡Œçš„对象。没崩溃的äh¾l§ç®‹çœ‹ä¾‹å­Dã€?br /> 例子DåQ?br />     String s1 = "java";<br />     String s2 = new String("java");<br />     System.out.print(s1.intern()==s2.intern());<br /> intern()是什么东东?反正¾l“果是true。如果没用过˜q™ä¸ªæ–ÒŽ(gu¨©)³•åQŒè€Œä¸”训练有素的程序员?sh¨´)¼š(x¨¬)去看JDK文档äº?ji¨£n)。简单点说就是用intern()æ–ÒŽ(gu¨©)³•ž®±å¯ä»¥ç”¨“==”比较字符串的内容äº?ji¨£n)。在我看到intern()æ–ÒŽ(gu¨©)³•到底有什么用之前åQŒæˆ‘è®¤äØ“(f¨´)它太多余äº?ji¨£n)。其实我写的˜q™ä¸€æ¡ä¹Ÿå¾ˆå¤šä½™ï¼Œintern()æ–ÒŽ(gu¨©)³•˜q˜å­˜åœ¨è¯¸å¤šçš„问题åQŒå¦‚效率、实çŽîC¸Šçš„不¾lŸä¸€……<br /> 例子EåQ?br />     String str1 = "java";<br />     String str2 = new String("java");<br />     System.out.print(str1.equals(str2));<br /> 无论在常量池˜q˜æ˜¯å †ä¸­çš„对象,用equals()æ–ÒŽ(gu¨©)³•比较的就是内容,ž®Þp¿™ä¹ˆç®€å•!看完此条的äh一定很后æ?zh¨¨n)”åQŒä½†æ˜¯åœ¨å¼€å§‹æˆ‘劝你别看äº?#8230;…<br /> <br /> 后记åQšç”¨å½ªå“¥çš„话è¯?#8220;有意思吗åQ?#8221;åQŒç¡®å®žæ²¡åŠŒÓ€‚在写这ŒD늚„时候我也是思量再三åQŒæ„Ÿè§‰è‡ªå·±åƒå­”ä¹™å·Þq‚«è€€“èŒ?#8221;字有几种写法。我查了(ji¨£n)一下茴 åQŒå›žåQŒå›˜åQŒå›¬åQŒè¿˜æœ‰ä¸€¿Uæ˜¯“å?#8221;字里面有ä¸?#8220;ç›?#8221;字,后面˜q™å››ä¸ªéƒ½åŠ ä¸Šè‰å­—å¤?#8230;…<br /> <img src ="http://www.aygfsteel.com/EricGu/aggbug/284780.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/EricGu/" target="_blank">Eric Gu</a> 2009-06-30 15:34 <a href="http://www.aygfsteel.com/EricGu/archive/2009/06/30/284780.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>FreeMarker设计指南(完整整理)http://www.aygfsteel.com/EricGu/archive/2009/06/18/282974.htmlEric GuEric GuThu, 18 Jun 2009 01:19:00 GMThttp://www.aygfsteel.com/EricGu/archive/2009/06/18/282974.htmlhttp://www.aygfsteel.com/EricGu/comments/282974.htmlhttp://www.aygfsteel.com/EricGu/archive/2009/06/18/282974.html#Feedback0http://www.aygfsteel.com/EricGu/comments/commentRss/282974.htmlhttp://www.aygfsteel.com/EricGu/services/trackbacks/282974.html快速入é—?

åQ?åQ‰æ¨¡æ?+ 数据模型 = 输出

FreeMarkeråŸÞZºŽè®¾è®¡è€…å’Œ½E‹åºå‘˜æ˜¯å…ähœ‰ä¸åŒä¸“业技能的不同个体的观念他们是分工力_Š¨çš„ï¼š(x¨¬)
设计者专注于表示——创建HTMLæ–‡äšg、图片、Web™åµé¢çš„其它可视化斚w¢åQ?br /> ½E‹åºå‘˜åˆ›å»ºç³»¾lŸï¼Œç”Ÿæˆè®¾è®¡™åµé¢è¦æ˜¾½Cºçš„æ•°æ®ã€?br /> ¾lå¸¸ä¼?x¨¬)遇到的问题是ï¼?x¨¬)在Web™åµé¢åQˆæˆ–其它¾cÕdž‹çš„æ–‡æ¡£ï¼‰(j¨ª)中显½Cºçš„信息在设计页面时是无效的åQŒæ˜¯åŸÞZºŽåŠ¨æ€æ•°æ®çš„ã€‚åœ¨˜q™é‡ŒåQŒä½ å¯ä»¥åœ¨HTMLåQˆæˆ–其它要输出的文本åQ‰ä¸­åŠ å…¥ä¸€äº›ç‰¹å®šæŒ‡ä»¤ï¼ŒFreeMarkerä¼?x¨¬)在输出™åµé¢¾l™æœ€¾lˆç”¨æˆäh—¶åQŒç”¨é€‚当的数据替代这些代码ã€?/p>

先来解释一下freemaker的基本语法了(ji¨£n)åQ?br /> <# ... > 中存放所有freemaker的内容,之外的内容全部原栯‚¾“出ã€?br /> <@ ... /> 是函数调ç”?br /> 两个定界½W¦å†…的内容中åQŒç¬¬ä¸€ä¸ªç¬¦å¯‚¡¨½CºæŒ‡ä»¤æˆ–者函数名åQŒå…¶åŽçš„跟随参数。freemaker提供的控制包括如下:(x¨¬)
<#if condition><#elseif condition><#else> 条äšg判断
<#list hash_or_seq as var> 遍历hash表或者collectionåQˆfreemaker¿UîC½œsequenceåQ‰çš„æˆå‘˜
<#macro name param1 param2 ... ><#nested param> 宏,无返回参æ•?br /> <#function name param1 param2><#return val>函数åQŒæœ‰˜q”回参数
var?member_function(...) 用函数对var˜q›è¡Œè½¬æ¢åQŒfreemaker¿UîCØ“(f¨´)build-ins。实际内部实现类似member_function(var, ...)
stringA[M .. N] 取子字符ä¸ÔŒ¼Œ¾cÖM¼¼substring(stringA, M, N)
{key:value, key2:value2 ...} 直接定义一个hash�br /> [item0, item1, item2 ...] 直接定义一个序�br /> hash0[key0] 存取hash表中key对应的元�br /> seq0[5] 存取序列指定下标的元�br /> <@function1 param0 param1 ... /> 调用函数function1
<@macro0 param0 param1 ; nest_param0 nest_param1 ...> nest_body <
/@macro> 调用宏,òq¶å¤„理宏的嵌å¥?br /> <#assign var = value > 定义变量òq¶åˆå§‹åŒ–
<#local var = value> åœ?macro 或è€?function ä¸­å®šä¹‰å±€éƒ¨å˜é‡åÆˆåˆå§‹åŒ?br /> <#global var = value > 定义全局变量òq¶åˆå§‹åŒ–
${var} 输出òq¶æ›¿æ¢äØ“(f¨´)表达式的å€?br /> <#visit xmlnode> 调用macro匚w…xmlnode本èínå?qi¨¢ng)其子节ç?br /> <#recurse xmlnode> 调用macro匚w…xmlnode的子节点


下面是一个例子:(x¨¬)

<html>
<head>
<title>Welcome!</title>
</head>
<body>
<h1>Welcome ${user}!</h1>
<p>Our latest product:
<a href="${latestProduct.url}">${latestProduct.name}</a>!
</body>
</html>
˜q™ä¸ªä¾‹å­æ˜¯åœ¨½Ž€å•çš„HTML中加入了(ji¨£n)一些由${…}包围的特定代码,˜q™äº›ç‰¹å®šä»£ç æ˜¯FreeMarker的指令,而包含FreeMarker的指令的文äšgž®Þq§°ä¸ºæ¨¡æ¿ï¼ˆTemplateåQ‰ã€?br /> 至于user、latestProduct.urlå’ŒlatestProduct.name来自于数据模型(data modelåQ‰ã€?br /> 数据模型ç”Þq¨‹åºå‘˜¾~–程来创建,向模板提供变化的信息åQŒè¿™äº›ä¿¡æ¯æ¥è‡ªäºŽæ•°æ®åº“、文ä»Óž¼Œç”šè‡³äºŽåœ¨½E‹åºä¸­ç›´æŽ¥ç”Ÿæˆã€?br /> 模板设计者不兛_¿ƒ(j¨©)数据从那儿来åQŒåªçŸ¥é“使用已经建立的数据模型ã€?br />

下面是一个可能的数据模型åQ?

(root)
|
+- user = "Big Joe"
|
+- latestProduct
|
+- url = "products/greenmouse.html"
|
+- name = "green mouse"
数据模型¾cÖM¼¼äºŽè®¡½Ž—机的文件系¾lŸï¼ŒlatestProduct可以看作是目录ã€?

2、数据模�

åQ?åQ‰åŸº¼‹€

在快速入门中介绍äº?ji¨£n)在模板中ä‹É用的三种基本对象¾cÕdž‹åQšscalars、hashes å’ŒsequencesåQŒå…¶å®žè¿˜å¯ä»¥æœ‰å…¶å®ƒæ›´å¤šçš„能力åQ?

  • scalarsåQšå­˜å‚¨å•å€?
  • hashesåQšå……当其它对象的容器åQŒæ¯ä¸ªéƒ½å…Œ™”一个唯一的查询名å­?
  • sequencesåQšå……当其它对象的容器åQŒæŒ‰‹Æ¡åºè®‰K—®
  • æ–ÒŽ(gu¨©)³•åQšé€šè¿‡ä¼ é€’的参数˜q›è¡Œè®¡ç®—åQŒä»¥æ–°å¯¹è±¡è¿”回结æž?
  • 用户自定义FTL标记åQšå®å’Œå˜æ¢å™¨

通常每个变量只具有上˜q°çš„一¿Uèƒ½åŠ›ï¼Œä½†ä¸€ä¸ªå˜é‡å¯ä»¥å…·æœ‰å¤šä¸ªä¸Š˜q°èƒ½åŠ›ï¼Œå¦‚ä¸‹é¢çš„ä¾‹å­åQ?

(root)
|
+- mouse = "Yerri"
|
+- age = 12
|
+- color = "brown">
mouse既是scalars又是hashesåQŒå°†ä¸Šé¢çš„æ•°æ®æ¨¡åž‹åˆòq¶åˆ°ä¸‹é¢çš„æ¨¡æ¿ï¼š(x¨¬)
${mouse}       <#-- use mouse as scalar -->
${mouse.age} <#-- use mouse as hash -->
${mouse.color} <#-- use mouse as hash -->
输出¾l“果是:(x¨¬)
Yerri
12
brown

åQ?åQ‰Scalar变量

Scalar变量存储单å€û|¼Œå¯ä»¥æ˜¯ï¼š(x¨¬)

  • 字符ä¸ÔŒ¼š(x¨¬)½Ž€å•文本,在模板中使用引号åQˆå•引号或双引号åQ‰æ‹¬èµ?
  • æ•°å­—åQšåœ¨æ¨¡æ¿ä¸­ç›´æŽ¥ä‹É用数字å€?
  • 日期åQšå­˜å‚¨æ—¥æœ?æ—‰™—´ç›¸å…³çš„æ•°æ®ï¼Œå¯ä»¥æ˜¯æ—¥æœŸã€æ—¶é—´æˆ–日期-æ—‰™—´åQˆTimestampåQ‰ï¼›é€šå¸¸æƒ…况åQŒæ—¥æœŸå€¼ç”±½E‹åºå‘˜åŠ åˆ°æ•°æ®æ¨¡åž‹ä¸­åQŒè®¾è®¡è€…只需要显½Cºå®ƒä»?
  • 布尔å€û|¼š(x¨¬)true或falseåQŒé€šå¸¸åœ?lt;#if …>标记中ä‹Éç”?

åQ?åQ‰hashes 、sequences和集å?

有些变量不包含ä“Q何可昄¡¤ºçš„å†…å®¹ï¼Œè€Œæ˜¯ä½œäØ“(f¨´)容器包含其它变量åQŒè€…有两种¾cÕdž‹åQ?

  • hashesåQšå…·æœ‰ä¸€ä¸ªå”¯ä¸€çš„æŸ¥è¯¢åå­—和它包含的每个变量相关è?
  • sequencesåQšä‹É用数字和它包含的每个变量相关联,索引å€ég»Ž0å¼€å§?

集合变量通常¾cÖM¼¼sequencesåQŒé™¤éžæ— æ³•访问它的大ž®å’Œä¸èƒ½ä½¿ç”¨ç´¢å¼•来获得它的子变量åQ›é›†åˆå¯ä»¥çœ‹ä½œåªèƒ½ç”±<#list …>指ä×o(h¨´)使用的受限sequences

åQ?åQ‰æ–¹æ³?

æ–ÒŽ(gu¨©)³•变量通常是基于给出的参数计算倹{€?

下面的例子假讄¡¨‹åºå‘˜å·²ç»ž®†æ–¹æ³•变量avg攑ֈ°æ•°æ®æ¨¡åž‹ä¸­ï¼Œç”¨æ¥è®¡ç®—æ•°å­—òq›_‡å€û|¼š(x¨¬)

The average of 3 and 5 is: ${avg(3, 5)}
The average of 6 and 10 and 20 is: ${avg(6, 10, 20)}
The average of the price of python and elephant is:
${avg(animals.python.price, animals.elephant.price)}

åQ?åQ‰å®å’Œå˜æ¢å™¨

宏和变换器变量是用户自定义指令(自定义FTL标记åQ‰ï¼Œä¼?x¨¬)在后面讲述˜q™äº›é«˜çñ”ç‰ÒŽ(gu¨©)€?

åQ?åQ‰èŠ‚ç‚?

节点变量表示为树(w¨¨i)型结构中的一个节点,通常在XML处理中ä‹É用,ä¼?x¨¬)在后面的专门章节中è?

3、模�

åQ?åQ‰æ•´ä½“结æž?

模板使用FTLåQˆF(tu¨¢n)reeMarker模板语言åQ‰ç¼–写,是下面各部分的一个组合:(x¨¬)

  • 文本åQšç›´æŽ¥è¾“å‡?
  • InterpolationåQšç”±${å’Œ}åQŒæˆ–#{å’Œ}来限定,计算值替代输å‡?
  • FTL标记åQšFreeMarker指ä×o(h¨´)åQŒå’ŒHTML标记¾cÖM¼¼åQŒåå­—前åŠ?予以区分åQŒä¸ä¼?x¨¬)输å?
  • 注释åQšç”±<#--å’?->限定åQŒä¸ä¼?x¨¬)输å?

下面是以一个具体模板例子:(x¨¬)

<html>
<head>
<title>Welcome!</title>
</head>
<body>
<#-- Greet the user with his/her name -->
<h1>Welcome ${user}!</h1>
<p>We have these animals:
<ul>
<#list animals as being>
<li>${being.name} for ${being.price} Euros
</#list>
</ul>
</body>
</html>

注意事项åQ?

  • FTL区分大小写,所以list是正¼‹®çš„FTL指ä×o(h¨´)åQŒè€ŒList不是åQ?{name}å’?{NAME}是不同的
  • Interpolation只能在文本中使用
  • FTL标记不能位于另一个FTL标记内部åQŒä¾‹å¦‚:(x¨¬)
<#if <#include 'foo'>='bar'>...</if>
  • 注释可以位于FTL标记和Interpolation内部åQŒå¦‚下面的例子:(x¨¬)
<h1>Welcome ${user <#-- The name of user -->}!</h1>
<p>We have these animals:
<ul>
<#list <#-- some comment... --> animals as <#-- again... --> being>
...
  • 余的½Iºç™½å­—符ä¼?x¨¬)在模板输出时移é?

åQ?åQ‰æŒ‡ä»?

在FreeMarker中,使用FTL标记引用指ä×o(h¨´)。有三种FTL标记åQŒè¿™å’ŒHTML标记是类似的åQ?

  • 开始标讎ͼš(x¨¬)<#directivename parameters>
  • ¾l“束标记åQ?lt;/#directivename>
  • ½Iºå†…å®ÒŽ(gu¨©)Œ‡ä»¤æ ‡è®ŽÍ¼š(x¨¬)<#directivename parameters/>

有两¿Uç±»åž‹çš„æŒ‡ä×o(h¨´)åQšé¢„定义指ä×o(h¨´)和用户定义指令ã€?

用户定义指ä×o(h¨´)要ä‹É用@替换#åQŒå¦‚<@mydirective>...</@mydirective>åQˆä¼š(x¨¬)在后面讲˜qŽÍ¼‰(j¨ª)ã€?

FTL标记不能够交叉,而应该正¼‹®çš„嵌套åQŒå¦‚下面的代码是错误的:(x¨¬)

<ul>
<#list animals as being>
<li>${being.name} for ${being.price} Euros
<#if use = "Big Joe">
(except for you)
</#list>
</#if> <#-- WRONG! -->
</ul>
如果使用不存在的指ä×o(h¨´)åQŒFreeMarker不会(x¨¬)使用模板输出åQŒè€Œæ˜¯äº§ç”Ÿä¸€ä¸ªé”™è¯¯æ¶ˆæ¯ã€?

FreeMarkerä¼?x¨¬)忽略FTL标记中的½Iºç™½å­—符åQŒå¦‚下面的例子:(x¨¬)

<#list
animals as
being
>
${being.name} for ${being.price} Euros
</#list >
但是åQ?lt;ã€?lt;/和指令之间不允许有空白字½W¦ã€?

åQ?åQ‰è¡¨è¾‘Ö¼

直接指定�/strong>

  • 字符ä¸?
使用单引åähˆ–双引号限å®?

如果包含ç‰ÒŽ(gu¨©)®Šå­—符需要è{义,如下面的例子åQ?

${"It's \"quoted\" and
this is a backslash: \\"}

${'It\'s "quoted" and
this is a backslash: \\'}
输出¾l“果是:(x¨¬)
It's "quoted" and
this is a backslash: \

It's "quoted" and
this is a backslash: \
下面是支持的转义序列åQ?
转义序列 含义
\" 双引�u0022)
\' 单引�u0027)

反斜�u005C)
\n 换行(u000A)
\r Return (u000D)
\t Tab (u0009)
\b Backspace (u0008)
\f Form feed (u000C)
\l <
\g >
\a &
\{ {
\xCode 4ä½?6˜q›åˆ¶Unicode代码

有一¾cȝ‰¹ŒDŠçš„字符串称为raw字符ä¸ÔŒ¼Œè¢«è®¤ä¸ºæ˜¯¾U¯æ–‡æœ¬ï¼Œå…¶ä¸­çš„\å’Œ{½{‰ä¸å…ähœ‰ç‰ÒŽ(gu¨©)®Šå«ä¹‰åQŒè¯¥¾cÕd­—½W¦ä¸²åœ¨å¼•号前面加råQŒä¸‹é¢æ˜¯ä¸€ä¸ªä¾‹å­ï¼š(x¨¬)

${r"${foo}"}

${r"C:\foo\bar"}
输出的结果是åQ?
${foo}

C:\foo\bar
  • æ•°å­—

直接输入åQŒä¸éœ€è¦å¼•å?

¾_‘Öº¦æ•°å­—使用“.”分隔åQŒä¸èƒ½ä‹É用分¾l„符å?

目前版本不支持科学计数法åQŒæ‰€ä»?#8220;1E3”是错误的

不能省略ž®æ•°ç‚¹å‰é¢çš„0åQŒæ‰€ä»?#8220;.5”是错误的

数字8�8�8�.00都是相同�

  • 布尔å€?

trueå’ŒfalseåQŒä¸ä½¿ç”¨å¼•号

  • 序列

由逗号分隔的子变量列表åQŒç”±æ–ÒŽ(gu¨©)‹¬å·é™å®šï¼Œä¸‹é¢æ˜¯ä¸€ä¸ªä¾‹å­ï¼š(x¨¬)

<#list ["winter", "spring", "summer", "autumn"] as x>
${x}
</#list>
输出的结果是åQ?
winter
spring
summer
autumn
列表的项目是表达式,所以可以有下面的例子:(x¨¬)
[2 + 2, [1, 2, 3, 4], "whatnot"]
可以使用数字范围定义数字序列åQŒä¾‹å¦?..5½{‰åŒäºŽ[2, 3, 4, 5]åQŒä½†æ˜¯æ›´æœ‰æ•ˆçŽ‡ï¼Œæ³¨æ„æ•°å­—èŒƒå›´æ²¡æœ‰æ–ÒŽ(gu¨©)‹¬å?

可以定义反递增的数字范å›ß_(d¨¢)¼Œå¦?..2

  • 散列åQˆhashåQ?
由逗号分隔的键/值列表,由大括号限定åQŒé”®å’Œå€ég¹‹é—´ç”¨å†’号分隔åQŒä¸‹é¢æ˜¯ä¸€ä¸ªä¾‹å­ï¼š(x¨¬)
{"name":"green mouse", "price":150}
键和值都是表辑ּåQŒä½†æ˜¯é”®å¿…须是字½W¦ä¸²

获取变量

  • ™å¶å±‚变量åQ?${variable}åQŒå˜é‡ååªèƒ½æ˜¯å­—母、数字、下划线ã€?、@å’?的组合,且不能以数字开å¤?
  • 从散列中获取数据

可以使用点语法或æ–ÒŽ(gu¨©)‹¬å¯‚¯­æ³•,假设有下面的数据模型åQ?

(root)
|
+- book
| |
| +- title = "Breeding green mouses"
| |
| +- author
| |
| +- name = "Julia Smith"
| |
| +- info = "Biologist, 1923-1985, Canada"
|
+- test = "title"
下面都是½{‰ä­h(hu¨¢n)的:(x¨¬)
book.author.name
book["author"].name
book.author.["name"]
book["author"]["name"]
使用点语法,变量名字有顶层变量一æ ïL(f¨¥ng)š„限制åQŒä½†æ–ÒŽ(gu¨©)‹¬å¯‚¯­æ³•没有该限制åQŒå› ä¸ºåå­—是ä»ÀL„è¡¨è¾¾å¼çš„¾l“æžœ
  • 从序列获得数据:(x¨¬)和散列的æ–ÒŽ(gu¨©)‹¬å¯‚¯­æ³•è¯­æ³•ä¸€æ øP¼Œåªæ˜¯æ–ÒŽ(gu¨©)‹¬å·ä¸­çš„表辑ּå€¼å¿…™åÀL˜¯æ•°å­—åQ›æ³¨æ„ï¼š(x¨¬)½W¬ä¸€ä¸ªé¡¹ç›®çš„索引æ˜?

序列片断åQšä‹É用[startIndex..endIndex]语法åQŒä»Žåºåˆ—中获得序列片断(也是序列åQ‰ï¼›startIndexå’ŒendIndexæ˜¯ç»“æžœäØ“(f¨´)数字的表辑ּ

  • ç‰ÒŽ(gu¨©)®Šå˜é‡åQšFreeMarker内定义变量,使用.variablename语法讉K—®

字符串操�

  • InterpolationåQˆæˆ–˜qžæŽ¥æ“ä½œåQ?

可以使用${..}åQˆæˆ–#{..}åQ‰åœ¨æ–‡æœ¬éƒ¨åˆ†æ’入表达式的å€û|¼Œä¾‹å¦‚åQ?

${"Hello ${user}!"}

${"${user}${user}${user}${user}"}
可以使用+操作½W¦èŽ·å¾—åŒæ ïL(f¨¥ng)š„¾l“æžœ
${"Hello " + user + "!"}

${user + user + user + user}
${..}只能用于文本部分åQŒä¸‹é¢çš„代码是错误的åQ?
<#if ${isBig}>Wow!</#if>

<#if "${isBig}">Wow!</#if>
应该写成åQ?
<#if isBig>Wow!</#if>
  • 子串

例子åQˆå‡è®¾userçš„å€égØ“(f¨´)“Big Joe”åQ‰ï¼š(x¨¬)

${user[0]}${user[4]}

${user[1..4]}
¾l“果是(注意½W¬ä¸€ä¸ªå­—½W¦çš„索引æ˜?åQ‰ï¼š(x¨¬)
BJ

ig J
序列操作
  • ˜qžæŽ¥æ“ä½œåQšå’Œå­—ç¬¦ä¸²ä¸€æ øP¼Œä½¿ç”¨+åQŒä¸‹é¢æ˜¯ä¸€ä¸ªä¾‹å­ï¼š(x¨¬)
<#list ["Joe", "Fred"] + ["Julia", "Kate"] as user>
- ${user}
</#list>
输出¾l“果是:(x¨¬)
- Joe
- Fred
- Julia
- Kate
散列操作
  • ˜qžæŽ¥æ“ä½œåQšå’Œå­—ç¬¦ä¸²ä¸€æ øP¼Œä½¿ç”¨+åQŒå¦‚果具有相同的keyåQŒå³è¾¹çš„值替代左边的å€û|¼Œä¾‹å¦‚åQ?
<#assign ages = {"Joe":23, "Fred":25} + {"Joe":30, "Julia":18}>
- Joe is ${ages.Joe}
- Fred is ${ages.Fred}
- Julia is ${ages.Julia}
输出¾l“果是:(x¨¬)
- Joe is 30
- Fred is 25
- Julia is 18
½Ž—术˜qç®—
  • åQ‹ã€ï¼ã€?#215;、/、%åQŒä¸‹é¢æ˜¯ä¸€ä¸ªä¾‹å­ï¼š(x¨¬)
${x * x - 100}
${x / 2}
${12 % 10}
输出¾l“果是(假设xä¸?åQ‰ï¼š(x¨¬)
-75
2.5
2
操作½W¦ä¸¤è¾¹å¿…™åÀL˜¯æ•°å­—åQŒå› æ­¤ä¸‹é¢çš„代码是错误的åQ?
${3 * "5"} <#-- WRONG! -->  
使用+操作½W¦æ—¶åQŒå¦‚果一è¾ÒŽ(gu¨©)˜¯æ•°å­—åQŒä¸€è¾ÒŽ(gu¨©)˜¯å­—符ä¸ÔŒ¼Œž®×ƒ¼š(x¨¬)自动ž®†æ•°å­—è{æ¢äØ“(f¨´)字符ä¸ÔŒ¼Œä¾‹å¦‚åQ?
${3 + "5"}  
输出¾l“果是:(x¨¬)
35
使用内徏的intåQˆåŽé¢è®²˜qŽÍ¼‰(j¨ª)获得整数部分åQŒä¾‹å¦‚:(x¨¬)
${(x/2)?int}
${1.1?int}
${1.999?int}
${-1.1?int}
${-1.999?int}
输出¾l“果是(假设xä¸?åQ‰ï¼š(x¨¬)
2
1
1
-1
-1
  • 比较操作½W?

使用=åQˆæˆ–==åQŒå®Œå…¨ç›¸½{‰ï¼‰(j¨ª)‹¹‹è¯•两个值是否相½{‰ï¼Œä½¿ç”¨!= ‹¹‹è¯•两个值是否不相等

=å’?=两边必须是相同类型的å€û|¼Œå¦åˆ™ä¼?x¨¬)äñ”生错误,例å¦?lt;#if 1 = "1">ä¼?x¨¬)引起错è?

Freemarker是精¼‹®æ¯”较,所以对"x"ã€?x "å’?X"是不相等çš?

å¯ÒŽ(gu¨©)•°å­—和日期可以使用<ã€?lt;=ã€?gt;å’?gt;=åQŒä½†ä¸èƒ½ç”¨äºŽå­—符ä¸?

ç”׃ºŽFreemarkerä¼?x¨¬)å°?gt;解释成FTL标记的结束字½W¦ï¼Œæ‰€ä»¥å¯¹äº?gt;å’?gt;=可以使用括号来避免这¿Uæƒ…况,例如<#if (x > y)>

另一¿Uæ›¿ä»£çš„æ–ÒŽ(gu¨©)³•是,使用lt、lte、gtå’Œgte来替ä»?lt;ã€?lt;=ã€?gt;å’?gt;=

  • 逻辑操作½W?

&&åQˆandåQ‰ã€||åQˆoråQ‰ã€?åQˆnotåQ‰ï¼Œåªèƒ½ç”¨äºŽå¸ƒå°”å€û|¼Œå¦åˆ™ä¼?x¨¬)äñ”生错è?

例子åQ?

<#if x < 12 && color = "green">
We have less than 12 things, and they are green.
</#if>
<#if !hot> <#-- here hot must be a boolean -->
It's not hot.
</#if>
  • 内徏函数

å†…å¾å‡½æ•°çš„ç”¨æ³•ç±»ä¼ÆD®¿é—®æ•£åˆ—的子变量,只是使用“?”替代“.”åQŒä¸‹é¢åˆ—出常用的一些函æ•?

    • 字符串ä‹É用的åQ?

htmlåQšå¯¹å­—符串进行HTML¾~–码

cap_firståQšä‹É字符串第一个字母大å†?

lower_caseåQšå°†å­—符串è{换成ž®å†™

upper_caseåQšå°†å­—符串è{换成大写

trimåQšåŽ»æŽ‰å­—½W¦ä¸²å‰åŽçš„空白字½W?

    • 序列使用的:(x¨¬)

sizeåQšèŽ·å¾—åºåˆ—ä¸­å…ƒç´ çš„æ•°ç›?

    • 数字使用的:(x¨¬)

intåQšå–得数字的整数部分åQˆå¦‚-1.9?int的结果是-1åQ?

例子åQˆå‡è®¾test保存字符ä¸?Tom & Jerry"åQ‰ï¼š(x¨¬)

${test?html}
${test?upper_case?html}
输出¾l“果是:(x¨¬)
Tom &amp; Jerry
TOM &amp; JERRY
  • 操作½W¦ä¼˜å…ˆé¡ºåº?
操作½W¦ç»„ 操作½W?
后缀 [subvarName] [subStringRange] . (methodParams)
一� +expr�expr�
内徏 ?
乘法 *�/ �
加法 +�
关系 <ã€?gt;ã€?lt;=ã€?gt;=åQˆlt、lte、gt、gteåQ?
相等 ==åQ?åQ‰ã€?=
逻辑and &&
逻辑or 双竖¾U?/td>
数字范围 ..

åQ?åQ‰Interpolation

Interpolation有两¿Uç±»åž‹ï¼š(x¨¬)

  1. 通用InterpolationåQ?{expr}
  1. æ•°å­—InterpolationåQ?{expr}æˆ?{expr; format}

注意åQšInterpolation只能用于文本部分

  • 通用Interpolation

插入字符串å€û|¼š(x¨¬)直接输出表达式结æž?

插入数字å€û|¼š(x¨¬)æ ÒŽ(gu¨©)®¾~ºçœæ ¼å¼åQˆç”±#setting指ä×o(h¨´)讄¡½®åQ‰å°†è¡¨è¾¾å¼ç»“æžœè{换成文本输出åQ›å¯ä»¥ä‹É用内建函数string格式化单个InterpolationåQŒä¸‹é¢æ˜¯ä¸€ä¸ªä¾‹å­ï¼š(x¨¬)

<#setting number_format="currency"/>
<#assign answer=42/>
${answer}
${answer?string} <#-- the same as ${answer} -->
${answer?string.number}
${answer?string.currency}
${answer?string.percent}
输出¾l“果是:(x¨¬)
$42.00
$42.00
42
$42.00
4,200%
插入日期å€û|¼š(x¨¬)æ ÒŽ(gu¨©)®¾~ºçœæ ¼å¼åQˆç”±#setting指ä×o(h¨´)讄¡½®åQ‰å°†è¡¨è¾¾å¼ç»“æžœè{换成文本输出åQ›å¯ä»¥ä‹É用内建函数string格式化单个InterpolationåQŒä¸‹é¢æ˜¯ä¸€ä¸ªä‹É用格式模式的例子åQ?
${lastUpdated?string("yyyy-MM-dd HH:mm:ss zzzz")}
${lastUpdated?string("EEE, MMM d, ''yy")}
${lastUpdated?string("EEEE, MMMM dd, yyyy, hh:mm:ss a '('zzz')'")}
输出的结果类ä¼ég¸‹é¢çš„æ ¼å¼åQ?
2003-04-08 21:24:44 Pacific Daylight Time
Tue, Apr 8, '03
Tuesday, April 08, 2003, 09:24:44 PM (PDT)
插入布尔å€û|¼š(x¨¬)æ ÒŽ(gu¨©)®¾~ºçœæ ¼å¼åQˆç”±#setting指ä×o(h¨´)讄¡½®åQ‰å°†è¡¨è¾¾å¼ç»“æžœè{换成文本输出åQ›å¯ä»¥ä‹É用内建函数string格式化单个InterpolationåQŒä¸‹é¢æ˜¯ä¸€ä¸ªä¾‹å­ï¼š(x¨¬)
<#assign foo=true/>
${foo?string("yes", "no")}
输出¾l“果是:(x¨¬)
yes
  • æ•°å­—Interpolationçš?{expr; format}形式可以用来格式化数字,format可以是:(x¨¬)

mXåQšå°æ•°éƒ¨åˆ†æœ€ž®Xä½?

MXåQšå°æ•°éƒ¨åˆ†æœ€å¤§Xä½?

例子åQ?

<#-- If the language is US English the output is: -->
<#assign x=2.582/>
<#assign y=4/>
#{x; M2} <#-- 2.58 -->
#{y; M2} <#-- 4 -->
#{x; m1} <#-- 2.6 -->
#{y; m1} <#-- 4.0 -->
#{x; m1M2} <#-- 2.58 -->
#{y; m1M2} <#-- 4.0 -->

4、杂™å?

åQ?åQ‰ç”¨æˆ·å®šä¹‰æŒ‡ä»?

宏和变换器变量是两种不同¾cÕdž‹çš„用户定义指令,它们之间的区别是宏是在模板中使用macro指ä×o(h¨´)定义åQŒè€Œå˜æ¢å™¨æ˜¯åœ¨æ¨¡æ¿å¤–ç”±½E‹åºå®šä¹‰åQŒè¿™é‡Œåªä»‹ç»å®?

  • 基本用法

宏是和某个变量关联的模板片断åQŒä»¥ä¾¿åœ¨æ¨¡æ¿ä¸­é€šè¿‡ç”¨æˆ·å®šä¹‰æŒ‡ä×o(h¨´)使用该变量,下面是一个例子:(x¨¬)

<#macro greet>
<font size="+2">Hello Joe!</font>
</#macro>
ä½œäØ“(f¨´)用户定义指ä×o(h¨´)使用宏变量时åQŒä‹É用@替代FTL标记中的#
<@greet></@greet>
如果没有体内容,也可以ä‹É用:(x¨¬)
<@greet/>
  • 参数

在macro指ä×o(h¨´)中可以在宏变量之后定义参敎ͼŒå¦‚:(x¨¬)

<#macro greet person>
<font size="+2">Hello ${person}!</font>
</#macro>
可以˜q™æ ·ä½¿ç”¨˜q™ä¸ªå®å˜é‡ï¼š(x¨¬)
<@greet person="Fred"/> and <@greet person="Batman"/> 
输出¾l“果是:(x¨¬)
  <font size="+2">Hello Fred!</font>

and <font size="+2">Hello Batman!</font>

宏的参数是FTL表达式,所以下面的代码å…ähœ‰ä¸åŒçš„æ„æ€ï¼š(x¨¬)

<@greet person=Fred/>
˜q™æ„å‘³ç€ž®†Fred变量的å€ég¼ ¾l™person参数åQŒè¯¥å€ég¸ä»…是字符ä¸ÔŒ¼Œ˜q˜å¯ä»¥æ˜¯å…¶å®ƒ¾cÕdž‹åQŒç”šè‡Ïx(ch¨®ng)˜¯å¤æ‚的表辑ּ

可以有多参数åQŒä¸‹é¢æ˜¯ä¸€ä¸ªä¾‹å­ï¼š(x¨¬)

<#macro greet person color>
<font size="+2" color="${color}">Hello ${person}!</font>
</#macro>
可以˜q™æ ·ä½¿ç”¨è¯¥å®å˜é‡åQ?
<@greet person="Fred" color="black"/> 
其中参数的次序是无关的,因此下面是等ä»ïL(f¨¥ng)š„åQ?
<@greet color="black" person="Fred"/>
只能使用在macro指ä×o(h¨´)中定义的参数åQŒåƈ且对所有参数赋å€û|¼Œæ‰€ä»¥ä¸‹é¢çš„代码是错误的åQ?
<@greet person="Fred" color="black" background="green"/>
<@greet person="Fred"/>
可以在定义参数时指定¾~ºçœå€û|¼Œå¦‚:(x¨¬)
<#macro greet person color="black">
<font size="+2" color="${color}">Hello ${person}!</font>
</#macro>
˜q™æ ·<@greet person="Fred"/>ž®±æ­£¼‹®äº†(ji¨£n)

宏的参数是局部变量,只能在宏定义中有�

  • 嵌套内容

用户定义指ä×o(h¨´)可以有嵌套内容,使用<#nested>指ä×o(h¨´)执行指ä×o(h¨´)开始和¾l“束标记之间的模板片æ–?

例子åQ?

<#macro border>
<table border=4 cellspacing=0 cellpadding=4><tr><td>
<#nested>
</tr></td></table>
</#macro>
˜q™æ ·ä½¿ç”¨è¯¥å®å˜é‡åQ?
<@border>The bordered text</@border>
输出¾l“æžœåQ?
  <table border=4 cellspacing=0 cellpadding=4><tr><td>
The bordered text
</tr></td></table>

<#nested>指ä×o(h¨´)可以被多‹Æ¡è°ƒç”¨ï¼Œä¾‹å¦‚åQ?

<#macro do_thrice>
<#nested>
<#nested>
<#nested>
</#macro>
<@do_thrice>
Anything.
</@do_thrice>
输出¾l“æžœåQ?
  Anything.
Anything.
Anything.
嵌套内容可以是有效的FTLåQŒä¸‹é¢æ˜¯ä¸€ä¸ªæœ‰äº›å¤æ‚的例子åQ?<@border> <ul> <@do_thrice> <li><@greet person="Joe"/> </@do_thrice> </ul> </@border> }}} 输出¾l“æžœåQ?
  <table border=4 cellspacing=0 cellpadding=4><tr><td>
<ul>
<li><font size="+2">Hello Joe!</font>
<li><font size="+2">Hello Joe!</font>
<li><font size="+2">Hello Joe!</font>
</ul>
</tr></td></table>
宏定义中的局部变量对嵌套内容是不可见的,例如åQ?
<#macro repeat count>
<#local y = "test">
<#list 1..count as x>
${y} ${count}/${x}: <#nested>
</#list>
</#macro>
<@repeat count=3>${y?default("?")} ${x?default("?")} ${count?default("?")}</@repeat>
输出¾l“æžœåQ?
    test 3/1: ? ? ?
test 3/2: ? ? ?
test 3/3: ? ? ?
  • 在宏定义中ä‹É用åó@环变é‡?

用户定义指ä×o(h¨´)可以有åó@环变量,通常用于重复嵌套内容åQŒåŸºæœ¬ç”¨æ³•是åQšä½œä¸ºnested指ä×o(h¨´)的参æ•îC¼ é€’åó@环变量的实际å€û|¼Œè€Œåœ¨è°ƒç”¨ç”¨æˆ·å®šä¹‰æŒ‡ä×o(h¨´)æ—Óž¼Œåœ?lt;@…>开始标记的参数后面指定循环变量的名å­?

例子åQ?

<#macro repeat count>
<#list 1..count as x>
<#nested x, x/2, x==count>
</#list>
</#macro>
<@repeat count=4 ; c, halfc, last>
${c}. ${halfc}<#if last> Last!</#if>
</@repeat>
输出¾l“æžœåQ?
  1. 0.5
2. 1
3. 1.5
4. 2 Last!

指定的åó@环变量的数目和用户定义指令开始标记指定的不同不会(x¨¬)有问é¢?

调用时少指定循环变量åQŒåˆ™å¤šæŒ‡å®šçš„å€ég¸å¯è§

调用时多指定循环变量åQŒå¤šä½™çš„循环变量不会(x¨¬)被创å»?

åQ?åQ‰åœ¨æ¨¡æ¿ä¸­å®šä¹‰å˜é‡?

在模板中定义的变量有三种¾cÕdž‹åQ?

  • plain变量åQšå¯ä»¥åœ¨æ¨¡æ¿çš„ä“Q何地方访问,包括使用include指ä×o(h¨´)插入的模板,使用assign指ä×o(h¨´)创徏和替æ?
  • 局部变量:(x¨¬)在宏定义体中有效åQŒä‹É用local指ä×o(h¨´)创徏和替æ?
  • 循环变量åQšåªèƒ½å­˜åœ¨äºŽæŒ‡ä×o(h¨´)的嵌套内容,由指令(如liståQ‰è‡ªåŠ¨åˆ›å»?

宏的参数是局部变量,而不是åó@环变量;局部变量隐藏(而不是覆盖)(j¨ª)同名的plain变量åQ›åó@环变量隐藏同名的局部变量和plain变量åQŒä¸‹é¢æ˜¯ä¸€ä¸ªä¾‹å­ï¼š(x¨¬)

<#assign x = "plain">
1. ${x} <#-- we see the plain var. here -->
<@test/>
6. ${x} <#-- the value of plain var. was not changed -->
<#list ["loop"] as x>
7. ${x} <#-- now the loop var. hides the plain var. -->
<#assign x = "plain2"> <#-- replace the plain var, hiding does not mater here -->
8. ${x} <#-- it still hides the plain var. -->
</#list>
9. ${x} <#-- the new value of plain var. -->
<#macro test>
2. ${x} <#-- we still see the plain var. here -->
<#local x = "local">
3. ${x} <#-- now the local var. hides it -->
<#list ["loop"] as x>
4. ${x} <#-- now the loop var. hides the local var. -->
</#list>
5. ${x} <#-- now we see the local var. again -->
</#macro>
输出¾l“æžœåQ?
1. plain
2. plain
3. local
4. loop
5. local
6. plain
7. loop
8. loop
9. plain2

内部循环变量隐藏同名的外部åó@环变量,如:(x¨¬)

<#list ["loop 1"] as x>
${x}
<#list ["loop 2"] as x>
${x}
<#list ["loop 3"] as x>
${x}
</#list>
${x}
</#list>
${x}
</#list>
输出¾l“æžœåQ?
  loop 1
loop 2
loop 3
loop 2
loop 1
模板中的变量ä¼?x¨¬)隐藏(而不是覆盖)(j¨ª)数据模型中同名变量,如果需要访问数据模型中的同名变量,使用ç‰ÒŽ(gu¨©)®Šå˜é‡globalåQŒä¸‹é¢çš„例子假设数据模型中的user的值是Big JoeåQ?
<#assign user = "Joe Hider">
${user} <#-- prints: Joe Hider -->
${.globals.user} <#-- prints: Big Joe -->

åQ?åQ‰åå­—空é—?

通常情况åQŒåªä½¿ç”¨ä¸€ä¸ªåå­—空é—ß_(d¨¢)¼Œ¿UîCØ“(f¨´)ä¸Õdå­—空é—?

ä¸ÞZº†(ji¨£n)创徏可重用的宏、变换器或其它变量的集合åQˆé€šå¸¸¿U°åº“åQ‰ï¼Œå¿…须使用多名字空é—ß_(d¨¢)¼Œå…¶ç›®çš„æ˜¯é˜²æ­¢åŒåå†²çª

  • 创徏åº?

下面是一个创建库的例子(假设保存在lib/my_test.ftl中)(j¨ª)åQ?

<#macro copyright date>
<p>Copyright (C) ${date} Julia Smith. All rights reserved.
<br>Email: ${mail}</p>
</#macro>
<#assign mail = "jsmith@acme.com">
使用import指ä×o(h¨´)导入库到模板中,Freemarkerä¼?x¨¬)äØ?f¨´)导入的库创徏新的名字½Iºé—´åQŒåƈ可以通过import指ä×o(h¨´)中指定的散列变量讉K—®åº“中的变量:(x¨¬)
<#import "/lib/my_test.ftl" as my>
<#assign mail="fred@acme.com">
<@my.copyright date="1999-2002"/>
${my.mail}
${mail}
输出¾l“æžœåQ?
  <p>Copyright (C) 1999-2002 Julia Smith. All rights reserved.
<br>Email: jsmith@acme.com</p>
jsmith@acme.com
fred@acme.com
可以看到例子中ä‹É用的两个同名变量òq¶æ²¡æœ‰å†²½Hï¼Œå› äØ“(f¨´)它们位于不同的名字空é—?

可以使用assign指ä×o(h¨´)在导入的名字½Iºé—´ä¸­åˆ›å»ºæˆ–替代变量åQŒä¸‹é¢æ˜¯ä¸€ä¸ªä¾‹å­ï¼š(x¨¬)

<#import "/lib/my_test.ftl" as my>
${my.mail}
<#assign mail="jsmith@other.com" in my>
${my.mail}
输出¾l“æžœåQ?
jsmith@acme.com
jsmith@other.com
数据模型中的变量ä»ÖM½•地方都可见,也包括不同的名字½Iºé—´åQŒä¸‹é¢æ˜¯ä¿®æ”¹çš„库åQ?
<#macro copyright date>
<p>Copyright (C) ${date} ${user}. All rights reserved.</p>
</#macro>
<#assign mail = "${user}@acme.com">
假设数据模型中的user变量的值是FredåQŒåˆ™ä¸‹é¢çš„代码:(x¨¬)
<#import "/lib/my_test.ftl" as my>
<@my.copyright date="1999-2002"/>
${my.mail}
输出¾l“æžœåQ?
  <p>Copyright (C) 1999-2002 Fred. All rights reserved.</p>
Fred@acme.com


补充åQˆé™(r¨´n)态方法的调用åQ‰ï¼š(x¨¬)


æ–ÒŽ(gu¨©)³•1åQ?/strong>
##定义配置文äšg freemarkerstatic.properties
_Validator=com.longyou.util.Validator
_Functions=com.longyou.util.Functions
_EscapeUtils=com.longyou.util.EscapeUtils
/调用代码
${_Functions.toUpperCase("Hello")}<br>
${_EscapeUtils.escape("狼的原野")}

æ–ÒŽ(gu¨©)³•2åQ?/strong>
${stack.findValue("@package.ClassName@method")}


补充åQšå¸¸ç”¨è¯­æ³?/strong>

EG.一个对象BOOK

1.输出 ${book.name}

½Iºå€¼åˆ¤æ–­ï¼š(x¨¬)${book.name?if_exists },

${book.name?default(‘xxx’)}//默认值xxx

${ book.name!"xxx"}//默认值xxx

日期格式åQ?{book.date?string('yyyy-MM-dd')}

数字格式åQ?{book?string.number}--20

${book?string.currency}--<#-- $20.00 -->

${book?string.percent}�lt;#-- 20% -->

插入布尔å€û|¼š(x¨¬)

<#assign foo=ture />

${foo?string("yes","no")} <#-- yes -->

 

 

 

 

2åQŽé€»è¾‘判断

a:

<#if condition>...

<#elseif condition2>...

<#elseif condition3>......

<#else>...

其中½Iºå€¼åˆ¤æ–­å¯ä»¥å†™æˆ?lt;#if book.name?? >

 

b:

<#switch value>

<#case refValue1>

...

<#break>

<#case refValue2>

...

<#break>

...

<#case refValueN>

...

<#break>

<#default>

...

 

3åQŽåó@环读å?/p>

<#list sequence as item>

...

½Iºå€¼åˆ¤æ–?lt;#if bookList?size = 0>

e.g.

<#list employees as e>

${e_index}. ${e.name}

输出:

1. Readonly

2. Robbin


freemarker中Mapçš„ä‹Éç”?/strong>
<#list testMap?keys as testKey>
       < option value="${testKey}" >
              ${testMap[testKey]}
     </option>
<
/#list>

freemarkerçš„Eclipse插äšg
  • If you use Eclipse 2.x:
    1. Open the Window menu, then Open Perspective -> Install/Update
    2. Click with the right mouse button on the Feature Updates view, then select New -> Site Bookmark
    3. In the displayed dialog box, type "FreeMarker" for Name and "http://www.freemarker.org/eclipse/update" for URL. Leave the "Bookmark type" radio buttons on "Eclipse update site".
    4. Click Finish
    5. Open the tree node under the newly created update site named "FreeMarker", select the "FreeMarker X.Y.Z" feature, and install it using the Install now button in the preview pane.
  • If you use Eclipse 3.x:
    1. Help -> Software updates -> Find and install....
    2. Choose "Search for new features to install".
    3. Click Add Update Site..., and type "FreeMarker" for Name and "http://www.freemarker.org/eclipse/update" for URL.
    4. Check the box of the "FreeMarker" feature.
    5. "Next"-s until it is installed...


]]>
J2SE5中的最新注释功能SuppressWarnings http://www.aygfsteel.com/EricGu/archive/2009/06/16/282626.htmlEric GuEric GuTue, 16 Jun 2009 08:02:00 GMThttp://www.aygfsteel.com/EricGu/archive/2009/06/16/282626.htmlhttp://www.aygfsteel.com/EricGu/comments/282626.htmlhttp://www.aygfsteel.com/EricGu/archive/2009/06/16/282626.html#Feedback0http://www.aygfsteel.com/EricGu/comments/commentRss/282626.htmlhttp://www.aygfsteel.com/EricGu/services/trackbacks/282626.html阅读全文

]]>
IntelliJ Idea 常用快捷键列è¡?/title><link>http://www.aygfsteel.com/EricGu/archive/2009/03/26/262020.html</link><dc:creator>Eric Gu</dc:creator><author>Eric Gu</author><pubDate>Thu, 26 Mar 2009 01:35:00 GMT</pubDate><guid>http://www.aygfsteel.com/EricGu/archive/2009/03/26/262020.html</guid><wfw:comment>http://www.aygfsteel.com/EricGu/comments/262020.html</wfw:comment><comments>http://www.aygfsteel.com/EricGu/archive/2009/03/26/262020.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/EricGu/comments/commentRss/262020.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/EricGu/services/trackbacks/262020.html</trackback:ping><description><![CDATA[<p>Alt+回èžR 导入åŒ?自动修正<span style="display: none"> Y#a 5Q;%C </span> <br /> Ctrl+N  查找¾c?span style="display: none"> }8dN-@% </span> <br /> Ctrl+Shift+N 查找文äšg<span style="display: none"> \$:/ad </span> <br /> Ctrl+Alt+L  格式化代ç ?span style="display: none"> ^vz>q?)N </span> <br /> Ctrl+Alt+O 优化导入的类和包<span style="display: none"> d B)QPI$ </span> <br /> Alt+Insert 生成代码(如get,setæ–ÒŽ(gu¨©)³•,构造函数等)<span style="display: none"> 8 A,,7dI </span> <br /> Ctrl+E或者Alt+Shift+C  最˜q‘更改的代码<span style="display: none"> {dS(}X&qw- </span> <br /> Ctrl+R 替换文本<span style="display: none"> m[NkF4K` </span> <br /> Ctrl+F 查找文本<span style="display: none"> nRgAKNV ) </span> <br /> Ctrl+Shift+Space 自动补全代码<span style="display: none"> ',+6'2ex </span> <br /> Ctrl+½Iºæ ¼ 代码提示<span style="display: none"> k-1Xx>g </span> <br /> Ctrl+Alt+Space ¾cÕdæˆ–接口名提示<span style="display: none"> vgX;@  </span> <br /> Ctrl+P æ–ÒŽ(gu¨©)³•参数提示<span style="display: none"> V#" )7P </span> <br /> Ctrl+Shift+Alt+N 查找¾cÖM¸­çš„æ–¹æ³•或变量<span style="display: none"> =1ov </span> <br /> Alt+Shift+C å¯ÒŽ(gu¨©)¯”最˜q‘修改的代码<span style="display: none"> r?PrlqOM </span> <br /> <span style="display: none"> B[+:q]7 </span> <br /> Shift+F6  重构-重命å?span style="display: none"> H["Jg)kJ </span> <br /> Ctrl+Shift+先上é”?span style="display: none"> ==ko,FJSV </span> <br /> Ctrl+X 删除è¡?span style="display: none"> rL 2+5| </span> <br /> Ctrl+D 复制è¡?span style="display: none"> gJmr $ </span> <br /> Ctrl+/ æˆ?Ctrl+Shift+/  注释åQ?/ 或è€?*...*/ åQ?span style="display: none"> hrkkRl </span> <br /> Ctrl+J  自动代码<span style="display: none"> i*+'FH </span> <br /> Ctrl+E 最˜q‘打开的文ä»?span style="display: none"> TM~yQ6K </span> <br /> Ctrl+H 昄¡¤º¾cȝ»“构图<span style="display: none"> 7OE|# </span> <br /> Ctrl+Q 昄¡¤ºæ³¨é‡Šæ–‡æ¡£<span style="display: none"> (LlsVoL2 </span> <br /> Alt+F1 查找代码所在位¾|?span style="display: none"> Fv}![ 7| </span> <br /> Alt+1 快速打开或隐藏工½E‹é¢æ?span style="display: none"> ]N='WJ(8/ </span> <br /> Ctrl+Alt+ left/right ˜q”回至上‹Æ¡æµè§ˆçš„位置<span style="display: none"> A[b.}3%f </span> <br /> Alt+ left/right 切换代码视图<span style="display: none"> XnN*gM l! </span> <br /> Alt+ Up/Down 在方法间快速移动定ä½?span style="display: none"> ^N=<b0rq </span> <br /> Ctrl+Shift+Up/Down 代码向上/下移动ã€?span style="display: none"> m4$mF/-Ny+ </span> <br /> F2 或Shift+F2 高ä(sh¨´)º®é”™è¯¯æˆ–警告快速定ä½?span style="display: none"> %}V4b </span> <br /> <span style="display: none">wsPWQvT </span> <br /> 代码标签输入完成后,按TabåQŒç”Ÿæˆä»£ç ã€?span style="display: none"> &3"n7 fmT </span> <br /> 选中文本åQŒæŒ‰Ctrl+Shift+F7 åQŒé«˜?sh¨´)º®æ˜¾½Cºæ‰€æœ‰è¯¥æ–‡æœ¬åQŒæŒ‰Esc高ä(sh¨´)º®æ¶ˆå¤±ã€?span style="display: none"> 5H`rQKU </span> <br /> Ctrl+W 选中代码åQŒè¿ž¾l­æŒ‰ä¼?x¨¬)有其他效æž?span style="display: none"> Ia87 </span> <br /> 选中文本åQŒæŒ‰Alt+F3 åQŒé€ä¸ªå¾€ä¸‹æŸ¥æ‰„¡›¸åŒæ–‡æœ¬ï¼Œòq‰™«˜?sh¨´)º®æ˜¾½Cºã€?span style="display: none"> ?Ge~7h- </span> <br /> Ctrl+Up/Down 光标跌™{到第一行或最后一行下<span style="display: none"> m@eohmV> </span> <br /> Ctrl+B 快速打开光标处的¾cÀLˆ–æ–ÒŽ(gu¨©)³• </p> <img src ="http://www.aygfsteel.com/EricGu/aggbug/262020.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/EricGu/" target="_blank">Eric Gu</a> 2009-03-26 09:35 <a href="http://www.aygfsteel.com/EricGu/archive/2009/03/26/262020.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>IntelliJ IDEA使用技巧一览表http://www.aygfsteel.com/EricGu/archive/2009/03/26/262019.htmlEric GuEric GuThu, 26 Mar 2009 01:33:00 GMThttp://www.aygfsteel.com/EricGu/archive/2009/03/26/262019.htmlhttp://www.aygfsteel.com/EricGu/comments/262019.htmlhttp://www.aygfsteel.com/EricGu/archive/2009/03/26/262019.html#Feedback0http://www.aygfsteel.com/EricGu/comments/commentRss/262019.htmlhttp://www.aygfsteel.com/EricGu/services/trackbacks/262019.html在ä‹Éç”?/font>InelliJ IDEA的过½E‹ä¸­åQŒé€šè¿‡æŸ¥æ‰¾èµ„料以及(qi¨¢ng)一些自å·Þqš„æ‘¸çƒ¦(ch¨³)åQŒå‘现这个众å¤?/font>Java½E‹åºå‘˜å–œ‹Æ¢çš„IDE里有许多值得一提的ž®çªé—¨ï¼Œå¦‚果能熟¾lƒçš„ž®†å®ƒä»¬åº”用于实际开发过½E‹ä¸­åQŒç›¸ä¿¡å®ƒä¼?x¨¬)大大节省你的开发时é—ß_(d¨¢)¼Œè€Œä¸”随之而来的还?sh¨´)¼š(x¨¬)有那么一点点成就感:(x¨¬)åQ?/font>Try itåQ?/font>
1、写代码时用Alt-InsertåQ?/font>Code|Generate…åQ‰å¯ä»¥åˆ›å»ºç±»é‡Œé¢ä»ÖM½•字段çš?/font>getterä¸?/font>setteræ–ÒŽ(gu¨©)³•ã€?/font>
2、右键点å‡?y¨¢n)L–­ç‚ÒŽ(gu¨©) ‡è®ŽÍ¼ˆåœ¨æ–‡æœ¬çš„左边栏里åQ‰æ¿€‹z»é€ŸæŸ¥èœå•åQŒä½ å¯ä»¥å¿«é€Ÿè®¾¾|?/font>enable/disable断点或者条件它的属性ã€?/font>
'300')this.width='300';if(this.height>'200')this.height='200';" border=0>
3ã€?/font>CodeCompletionåQˆä»£ç å®Œæˆï¼‰(j¨ª)属性里的一个特ŒDŠçš„变量是,‹È€‹z?/font>Ctrl-Alt-Space可以完成在或不在当前文äšg里的¾cÕdã€‚如果类没有引入åˆ?/font>import标志ä¼?x¨¬)自动创建ã€?/font>
'300')this.width='300';if(this.height>'200')this.height='200';" border=0>
4、ä‹Éç”?/font>Ctrl-Shift-V快捷键可以将最˜q‘ä‹É用的剪脓(chu¨¤ng)板内定w€‰æ‹©æ’入到文本。ä‹É用时¾pȝ»Ÿä¼?x¨¬)å¼¹å‡ÞZ¸€ä¸ªå«æœ‰å‰ªè´´å†…容的对话框,从中你可以选择你要¾_˜è„“(chu¨¤ng)的部分ã€?/font>
5、利ç”?/font>CodeCompletionåQˆä»£ç å®Œæˆï¼‰(j¨ª)属性可以快速地在代码中完成各种不同地语句,æ–ÒŽ(gu¨©)³•是先键入一个类名地前几个字母然后再ç”?/font>Ctrl-Space完成全称。如果有多个选项åQŒå®ƒä»¬ä¼š(x¨¬)列在速查列表里ã€?/font>
 '300')this.width='300';if(this.height>'200')this.height='200';" border=0>
6、用Ctrl-/�/font>Ctrl-Shift-/来注�/font>/反注释代码行与代码块�/font>
-/用单行注释标讎ͼˆ“//…”åQ‰æ¥æ³¨é‡Š/反注释当前行或者选择åœîC»£ç å—。è€?/font>Ctrl-Shift-/则可以用块注释标讎ͼˆ“/ V;}HGn  
dy/?S GW  
/
”åQ‰æŠŠæ‰€é€‰å—包围èµäh¥ã€‚要反注释一个代码块ž®±åœ¨å—中ä»ÖM½•一个地æ–ÒŽ(gu¨©)Œ‰Ctrl-Shift-/卛_¯ã€?/font>
7、按Alt-QåQ?/font>View|Context InfoåQ‰å¯ä»¥ä¸éœ€è¦ç§»åŠ¨ä»£ç å°±èƒ½æŸ¥çœ‹å½“å‰æ–¹æ³•åœ°å£°æ˜Žã€‚è¿ž¾l­æŒ‰ä¸¤æ¬¡ä¼?x¨¬)显½Cºå½“前所¾~–辑的类名ã€?/font>
8、ä‹Éç”?/font>Refactor|Copy Class…可以创徏一个所选择的类çš?#8220;副本”。这一点很有用åQŒæ¯”如,在你惌™¦åˆ›å¾ä¸€ä¸ªå¤§éƒ¨åˆ†å†…容都和已存在类相同的类时ã€?/font>
9、在¾~–辑器里Ctrl-D可以复制选择的块或者没有所选块是的当前行ã€?/font>
10ã€?/font>Ctrl-WåQˆé€‰æ‹©å­—)(j¨ª)在编辑器里的功能是先选择脱字½W¦å¤„的单词,然后选择源代码的扩展区域。ä‹D例来è¯ß_(d¨¢)¼Œå…ˆé€‰æ‹©ä¸€ä¸ªæ–¹æ³•名åQŒç„¶åŽæ˜¯è°ƒç”¨˜q™ä¸ªæ–ÒŽ(gu¨©)³•的表辑ּåQŒç„¶åŽæ˜¯æ•´ä¸ªè¯­å¥åQŒç„¶åŽåŒ…容块åQŒç­‰½{‰ã€?/font>
11、如果你不想让指½CÞZº‹ä»¶ç»†èŠ‚çš„“亮球”图标在编辑器上显½Cºï¼Œé€šè¿‡æŒ?/font>Alt-Enter¾l„合键打开所有事件列表然后用鼠标点击它就可以把这个事件文本附件的亮球¾|®æˆéžæ´»åŠ¨çŠ¶æ€ã€?/font>
˜q™æ ·ä»¥åŽž®×ƒ¸ä¼?x¨¬)有指示ç‰Ò?gu¨©)®Šäº‹äšg的亮球出çŽîCº†(ji¨£n)åQŒä½†æ˜¯ä½ ä»ç„¶å¯ä»¥ç”?/font>Alt-Enter快捷键ä‹É用它ã€?/font>
12、在使用CodeCompletionæ—Óž¼Œå¯ä»¥ç”¨é€—点åQ?/font>.åQ‰å­—½W¦ï¼Œé€—号åQˆï¼ŒåQ‰åˆ†åøP¼ˆåQ›ï¼‰(j¨ª)åQŒç©ºæ ¼å’Œå…¶å®ƒå­—符输入弹出列表里的当前高ä(sh¨´)º®éƒ¨åˆ†ã€‚选择的名字会(x¨¬)随着输入的字½W¦è‡ªåŠ¨è¾“å…¥åˆ°¾~–辑器里ã€?/font>
13、在ä»ÖM½•工具½H—口里ä‹Éç”?/font>Escape键都可以把焦点移到编辑器上ã€?/font>
Shift-Escape不仅可以把焦点移到编辑器上而且˜q˜å¯ä»¥éšè—å½“前(或最后活动的åQ‰å·¥å…ïL(f¨¥ng)ª—口ã€?/font>
F12键把焦点从编辑器¿UÕdˆ°æœ€˜q‘ä‹É用的工具½H—口ã€?/font>
14、在调试½E‹åºæ—¶æŸ¥çœ‹ä“Q何表辑ּå€¼çš„一个容易的æ–ÒŽ(gu¨©)³•ž®±æ˜¯åœ¨ç¼–辑器中选择文本åQˆå¯ä»¥æŒ‰å‡ æ¬¡Ctrl-W¾l„合键更有效地执行这个操作)(j¨ª)然后æŒ?/font>Alt-F8ã€?/font>
15、要打开¾~–辑器脱字符处ä‹É用的¾cÀLˆ–者方æ³?/font>Java文档的浏览器åQŒå°±æŒ?/font>Shift-F1åQˆå³é”®èœå•çš„External JavaDocåQ‰ã€?/font>
要ä‹É用这个功能须要把加入‹¹è§ˆå™¨çš„路径åQŒåœ¨“General”选项中设¾|®ï¼ˆOptions | IDE SettingsåQ‰ï¼Œå¦å¤–˜q˜è¦æŠŠåˆ›å»ºçš„Java文档加入到工½E‹ä¸­åQ?/font>File | Project PropertiesåQ‰ã€?/font>
16、用Ctrl-F12åQ?/font>View | File Structure PopupåQ‰é”®ä½ å¯ä»¥åœ¨å½“前¾~–辑的文件中快速导航ã€?/font>
˜q™æ—¶å®ƒä¼š(x¨¬)昄¡¤ºå½“前¾cÈš„æˆå‘˜åˆ—è¡¨ã€‚é€‰ä¸­ä¸€ä¸ªè¦å¯ÆDˆªçš„元素然后按Enter键或F4键。要è½ÀL¾åœ°å®šä½åˆ°åˆ—表中的一个条目,只需键入它的名字卛_¯ã€?/font>
17、在代码中把光标¾|®äºŽæ ‡è®°½W¦æˆ–者它的检查点上再æŒ?/font>Alt-F7åQˆå³é”®èœå•中çš?/font>Find Usages…åQ‰ä¼š(x¨¬)很快地查扑ֈ°åœ¨æ•´ä¸ªå·¥½E‹ä¸­ä½¿ç”¨åœ°æŸä¸€ä¸ªç±»ã€æ–¹æ³•或者变量的位置ã€?/font>
18、按Ctrl-NåQ?/font>Go to | Class…åQ‰å†é”®å…¥¾cȝš„名字可以快速地在编辑器里打开ä»ÖM½•一个类。从昄¡¤ºå‡ºæ¥çš„下拉列表里选择¾c…R€?/font>
'300')this.width='300';if(this.height>'200')this.height='200';" border=0>
同样的方法你可以通过使用Ctrl-Shift-NåQ?/font>Go to | File…åQ‰æ‰“开工程中的é?/font>Javaæ–‡äšgã€?/font>
19ã€è¦å¯ÆDˆªä»£ç ä¸­ä¸€äº›åœ°æ–¹ä‹É用到的类、方法或者变量的声明åQŒæŠŠå…‰æ ‡æ”‘Öœ¨æŸ¥çœ‹™å¹ä¸Šå†æŒ‰Ctrl-B卛_¯ã€‚也可以通过æŒ?/font>Ctrl键的同时在查看点上单击鼠标键调è{到声明处ã€?/font>
'300')this.width='300';if(this.height>'200')this.height='200';" border=0>
20、把光标攑ֈ°æŸ¥çœ‹ç‚¹ä¸Šå†æŒ‰Ctrl-Alt-Bå¯ä»¥å¯ÆDˆªåˆîC¸€ä¸ªæŠ½è±¡æ–¹æ³•的实现代码ã€?/font>
21、要看一个所选择的类的ç‘ô承层‹Æ¡ï¼ŒæŒ?/font>Ctrl-HåQ?/font>Browse Type HierarchyåQ‰å³å¯ã€‚也可以‹È€‹zȝ¼–辑器中的¾l§æ‰¿å…³ç³»è§†å›¾æŸ¥çœ‹å½“前¾~–辑¾cȝš„¾l§æ‰¿å…³ç³»ã€?/font>
 '300')this.width='300';if(this.height>'200')this.height='200';" border=0>
22、ä‹Éç”?/font>Ctrl-Shift-F7åQ?/font>Search | Highlight Usages in FileåQ‰å¯ä»¥å¿«é€Ÿé«˜?sh¨´)º®æ˜¾½Cºå½“前文件中某一变量的ä‹É用地斏V€‚按Escape清除高ä(sh¨´)º®æ˜„¡¤ºã€?/font>
23、用Alt-F3åQ?/font>Search | Incremental SearchåQ‰åœ¨¾~–辑器中实现快速查查找功能ã€?/font>
åœ?#8220;Search for:”提示工具里输入字½W¦ï¼Œä½¿ç”¨½Ž­å¤´é”®æœå‰å’ŒæœåŽæœçƒ¦(ch¨³)。按Escape退出ã€?/font>
24、按Ctrl-J¾l„合键来执行一些你è®îC¸èµäh¥çš?/font>Live Template¾~©å†™ã€‚比如,é”?#8220;it”然后æŒ?/font>Ctrl-J看看有什么发生ã€?/font>
'300')this.width='300';if(this.height>'200')this.height='200';" border=0>
25ã€?/font>Introduce Variable整合帮助你简化代码中复杂的声明。ä‹D个例子,在下面的代码片断里,在代码中选择一个表辑ּåQ?/font>
'300')this.width='300';if(this.height>'200')this.height='200';" border=0>
然后æŒ?/font>Ctrl-Alt-VåQ?/font>Refactor | Introduce VariableåQ‰å°±ä¼?x¨¬)出çŽîC¸‹é¢çš„¾l“æžœåQ?/font>
'300')this.width='300';if(this.height>'200')this.height='200';" border=0>
26ã€?/font>Ctrl-Shift-Jå¿«æ·é”®æŠŠä¸¤è¡Œåˆæˆä¸€è¡ŒåÆˆæŠŠä¸å¿…è¦çš„ç©ºæ ¼åŽ»æŽ‰ä»¥åŒšw…ä½ çš„代码格式ã€?/font>
27ã€?/font>Ctrl-Shift-BackspaceåQ?/font>Go to | Last Edit LocationåQ‰è®©ä½ è°ƒè½¬åˆ°ä»£ç ä¸­æ‰€åšæ”¹å˜çš„æœ€åŽä¸€ä¸ªåœ°æ–V€?/font>
多按几次Ctrl-Shift-Backspace查看更深的修改历双Ӏ?/font>
28、用Tools | Reformat Code…æ ÒŽ(gu¨©)®ä½ çš„代码样式参考(查看Options | IDE Setting | Code StyleåQ‰æ ¼å¼åŒ–代码ã€?/font>
使用Tools | Optimize Imports…可以æ ÒŽ(gu¨©)®è®„¡½®åQˆæŸ¥çœ?/font>Options | IDE Setting | Code Style | ImportsåQ‰è‡ªåŠ?#8220;优化”importsåQˆæ¸…除无用的imports½{‰ï¼‰(j¨ª)ã€?/font>
29、ä‹Éç”?/font>IDEAçš?/font>Live Templates | Live Templates让你在眨眼间创徏许多典型代码。比如,在一个方法里键入
'300')this.width='300';if(this.height>'200')this.height='200';" border=0>
再按Tab键看有什么事情发生了(ji¨£n)ã€?/font>
'300')this.width='300';if(this.height>'200')this.height='200';" border=0>
�/font>Tab键在不同的模板域内移动。查�/font>Options | Live Templates获取更多的细节�/font>
30、要查看一个文件中修改的本地历åÔŒ¼Œ‹È€‹zÕd³é”®èœå•里çš?/font>Local VCS | Show History…ã€‚ä¹Ÿè®æ€½ å¯ä»¥å¯ÆDˆªä¸åŒçš„æ–‡ä»¶ç‰ˆæœ¬ï¼Œçœ‹çœ‹å®ƒä»¬çš„不同之处再回滚åˆîC»¥å‰çš„ä»ÖM½•一个版本吧ã€?/font>
使用同样的右键菜单条目还可以看到一个目录里修改的历双Ӏ‚有äº?ji¨£n)这个特性你ž®×ƒ¸ä¼?x¨¬)丢å¤×ƒ“Q何代码了(ji¨£n)ã€?/font>
31、如果要äº?ji¨£n)解主菜单里每一个条目的用途,把鼠标指针移到菜单条目上再应用程序框架的底部的状态栏里就ä¼?x¨¬)显½Cºå®ƒä»¬çš„一些简短描˜qŽÍ¼Œä¹Ÿè®¸ä¼?x¨¬)对你有帮助ã€?/font>
32、要在编辑器里显½Cºæ–¹æ³•间的分隔线åQŒæ‰“å¼€Options | IDE Settings | EditoråQŒé€‰ä¸­“Show method separators”‹‚€(g¨¨)查盒åQ?/font>checkboxåQ‰ã€?/font>
33ã€?strong>ç”?/strong>Alt-Upå’?/font>Alt-Down键可以在¾~–辑器里不同的方法之间快速移动ã€?/font>
34、用F2/Shift-F2键在高ä(sh¨´)º®æ˜„¡¤ºçš„语法错误间跌™{ã€?/font>
ç”?/font>Ctrl-Alt-Down/Ctrl-Alt-Up快捷键则可以在编译器错误信息或者查找操作结果间跌™{ã€?/font>
35、通过æŒ?/font>Ctrl-OåQ?/font>Code | Override Methods…åQ‰å¯ä»¥å¾ˆå®ÒŽ(gu¨©)˜“地重载基本类地方法ã€?/font>
要完成当前类implements的(或者抽象基本类的)(j¨ª)接口的方法,ž®×ƒ‹Éç”?/font>Ctrl-IåQ?/font>Code | Implement Methods…åQ‰ã€?/font>
36、如果光标置于一个方法调用的括号é—ß_(d¨¢)¼ŒæŒ?/font>Ctrl-Pä¼?x¨¬)显½CÞZ¸€ä¸ªå¯ç”¨å‚数的列表ã€?/font>
'300')this.width='300';if(this.height>'200')this.height='200';" border=0>
37、要快速查看编辑器脱字½W¦å¤„使用的类或方法的Java文档åQŒæŒ‰Ctrl-QåQˆåœ¨å¼¹å‡ºèœå•çš?/font>Show Quick JavaDoc里)(j¨ª)卛_¯ã€?/font>
'300')this.width='300';if(this.height>'200')this.height='200';" border=0>
38、像Ctrl-QåQ?/font>Show Quick JavaDoc昄¡¤º½Ž€‹z?/font>Java文档åQ‰ï¼ŒCtrl-PåQ?/font>Show Parameter Info昄¡¤ºå‚数信息åQ‰ï¼ŒCtrl-BåQ?/font>Go to Declarationè·Œ™{到声明)(j¨ª)åQ?/font>Shift-F1åQ?/font>External JavaDoc外部Java文档åQ‰ä»¥å?qi¨¢ng)其它一些快捷键不仅可以在编辑器里ä‹É用,也可以应用在代码完成右键列表里ã€?/font>
39ã€?/font>Ctrl-EåQ?/font>View | Recent FilesåQ‰å¼¹å‡ºæœ€˜q‘访问的文äšg右键列表。选中文äšgæŒ?/font>Enter键打开ã€?/font>
40、在IDEA中可以很å®ÒŽ(gu¨©)˜“地对你的¾c»ï¼Œæ–ÒŽ(gu¨©)³•以及(qi¨¢ng)变量˜q›è¡Œé‡å‘½ååƈ在所有ä‹É用到它们的地方自动更正ã€?/font>
试一下,把编辑器脱字½W¦ç½®äºŽä“Q何一个变量名字上然后æŒ?/font>Shift-F6åQ?/font>Refactor | Rename…åQ‰ã€‚在对话框里键入要显½Cºåœ°æ–°åå­—再æŒ?/font>Enter。你ä¼?x¨¬)浏览到使用˜q™ä¸ªå˜é‡åœ°æ‰€æœ‰åœ°æ–¹ç„¶åŽæŒ‰“Do Refactor”按钮¾l“束重命名操作ã€?/font>
41、要在ä“Q何视图(Project View工程视图åQ?/font>Structure View¾l“构视图或者其它视图)(j¨ª)里快é€?/font>
选择当前¾~–辑地部分(¾c»ï¼Œæ–‡äšgåQŒæ–¹æ³•或者字ŒDµï¼‰(j¨ª)åQŒæŒ‰Alt-F1åQ?/font>View | Select in…åQ‰ã€?/font>
'300')this.width='300';if(this.height>'200')this.height='200';" border=0>
42、在“new”字符后实例化一个已知类型对象时也许你会(x¨¬)用到SmartType代码完成˜q™ä¸ªç‰ÒŽ(gu¨©)€§ã€‚比如,键入
 '300')this.width='300';if(this.height>'200')this.height='200';" border=0>
再按Ctrl-Shift-SpaceåQ?/font>
'300')this.width='300';if(this.height>'200')this.height='200';" border=0>
43、通过使用SmartType代码完成åQŒåœ¨IDEA中创建接口的整个匿名implementation也是非常å®ÒŽ(gu¨©)˜“的,比如åQŒå¯¹äºŽä¸€äº?/font>listeneråQˆç›‘听器åQ‰ï¼Œå¯ä»¥é”®å…¥
  Component component;
  component.addMouseListener(
    new w w <caret is here> 
  );
然后再按Ctrl-Shift-Space看看有什么发生了(ji¨£n)ã€?/font>
44、在你需要设¾|®ä¸€ä¸ªå·²çŸ¥ç±»åž‹çš„表达式的值时ç”?/font>SmartType代码完成也很有帮助。比如,键入
String s = (<caret is here> 
再按Ctrl-Shift-Space看看ä¼?x¨¬)有什么出现ã€?/font>
45、在所有视å›ùN‡Œéƒ½æä¾›äº†(ji¨£n)速查功能åQšåœ¨æ ?w¨¨i)里只需键入字符ž®±å¯ä»¥å¿«é€Ÿå®šä½åˆ°ä¸€ä¸ªæ¡ç›®ã€?/font>
46、当你想用代码片断捕捉异常时åQŒåœ¨¾~–辑器里选中˜q™ä¸ªç‰‡æ–­åQŒæŒ‰Ctrl-Alt-TåQ?/font>Code | Surround with…åQ‰ç„¶åŽé€‰æ‹©try/catch。它ä¼?x¨¬)自动äñ”生代码片断中抛出的所有异常的捕捉块。在Options | File Templates | Code tab中你˜q˜å¯ä»¥è‡ªå·±å®šåˆ¶äñ”生捕捉块的模æÑ€?/font>
用列表中的其它项可以包围别的一些结构�/font>
'300')this.width='300';if(this.height>'200')this.height='200';" border=0>
47、在使用代码完成æ—Óž¼Œç”?/font>Tab键可以输入弹出列表里的高?sh¨´)º®æ˜¾½Cºéƒ¨åˆ†ã€?/font>
不像ç”?/font>Enter键接受输入,˜q™ä¸ªé€‰ä¸­çš„名字会(x¨¬)覆盖掉脱字符双™¾¹åå­—的其它部分。这一点在用一个方法或者变量名替换另一个时特别有用ã€?/font>
48、在声明一个变量时代码完成ç‰ÒŽ(gu¨©)€§ä¼š(x¨¬)¾l™ä½ æ˜„¡¤ºä¸€ä¸ªå¾è®®åã€‚比如,开始键å…?/font>“private FileOutputStream”然后æŒ?/font>Ctrl-Space
'300')this.width='300';if(this.height>'200')this.height='200';" border=0>
åœ?/font>Options | IDE Setting | Code Style中还可以为本地变量,参数åQŒå®žä¾‹åŠ(qi¨¢ng)é?r¨´n)态字ŒDµå®šåˆ¶åå­—ã€?br />


]]>
Ö÷Õ¾Ö©Öë³ØÄ£°å£º ·ÚÎ÷ÏØ| ÐÃÖÝÊÐ| ºÚÁú½­Ê¡| ¾ÅÁúÏØ| ÆîÁ¬ÏØ| ×ÔÖÎÏØ| »Ȱ| Óå±±Çø| ÉÂÎ÷Ê¡| ÎåÔ­ÏØ| ±±°²ÊÐ| н¨ÏØ| ºáÉ½ÏØ| С½ðÏØ| ÓªÉ½ÏØ| ÐËÒåÊÐ| ÁÙÒÊÊÐ| Û²³ÇÏØ| ÐÅÑôÊÐ| ÎÚÀ¼ºÆÌØÊÐ| ÒËÐËÊÐ| ·±²ýÏØ| Ñ·¿ËÏØ| º£µíÇø| ƽ²ýÏØ| ĵµ¤½­ÊÐ| ÕżҴ¨| ±±º£ÊÐ| ·ÚÑôÊÐ| èµÉ½ÏØ| ÀÖÍ¤ÏØ| Èê³ÇÏØ| ÌìË®ÊÐ| È«ÄÏÏØ| ½õÆÁÏØ| ±¦¼¦ÊÐ| ÄÏľÁÖÏØ| ¸ß¶û·ò| ׿×ÊÏØ| ºÍË³ÏØ| ²ÔÄÏÏØ|