java注解实践-java开发java经验技巧

java注解实践-java开发java经验技巧

ID:30778121

大小:154.83 KB

页数:17页

时间:2019-01-03

上传者:U-991
java注解实践-java开发java经验技巧_第1页
java注解实践-java开发java经验技巧_第2页
java注解实践-java开发java经验技巧_第3页
java注解实践-java开发java经验技巧_第4页
java注解实践-java开发java经验技巧_第5页
资源描述:

《java注解实践-java开发java经验技巧》由会员上传分享,免费在线阅读,更多相关内容在工程资料-天天文库

Java注解实践-Java开发Java经验技巧Java注解实践原文出处:翡青注解对代码的语意没冇直接影响,他们只负责提供信息给相关的程序使用.?注解永远不会改变被注解代码的含义,但可以通过工具对被注解的代码进行特殊处理.JDK基本Annotation注解©Override©Deprecated©SuppressWarnings(value二〃unchecked")@SafeVarargs©Functionallntcrfacc•value特权如果使用注解吋只需耍为value成员变量指定值,则使用注解时可以直接在该注解的括号中指定value值,而无需使用name二value的形式.如@SuppressWarnings("unchecked")(SuppressWarnings的各种参数请参考解析@SupprcssWamings的各种参数)•诘坚持使用Override注解:如果在每个方法中使用Override注解来声明要覆盖父类声明,编译器就可以替你防止大量的错误.JDK元Annotation元Annotation用于修饰It他的Annotation定义.元注解©Retention注角@Target注倂@Documcnted注询©Inherited注侨 ©Retention?注解的保翩策略©Documented©Retention(RetentionPolicy.RUNTIME)@Target(ElementType.ANNOTATTON_TYPE)public@interfaceRetention{RetentionPolicyvalue();}value为SOURCE,?CLASS,?RUNTIME三值之一:publicenumRetentionPolicy{/***Annotationsaretobediscardedbythecompiler.*/SOURCE,/***Annotationsaretoberecordedintheclassfilebythecompiler*butneednotberetainedbytheVMatruntime.Thisisthedefault*behavior.*/CLASS,/***Annotationsaretoberecordedintheclassfilebythecompilerand*retainedbytheVMatruntime,sotheymaybereadreflcctively.**©seejava.lang,reflect.AnnotatedElement*/RUNTIME}•©Target?指定Annotation可以放宜的位置(被修饰的目标)©Documented©Retention(RetentionPolicy.RUNTIME)@Target(ElementType.ANNOTATTON_TYPE)public@intcrfaccTarget{ElementType[]value(); publicenumElementType{/**Class,interface(includingannotationtype),orenumdeclaration*/TYPE,/**Fielddeclaration(includesenumconstants)*/FIELD,/**Methoddeclaration*/METHOD,/**Parameterdeclaration*/PARAMETER,/**Constructordeclaration*/CONSTRUCTOR,/**Localvariabledeclaration*/LOCAL_VARTABLE,/**Annotationtypedeclaration*/ANNOTATION_TYPE,/**Packagedeclaration*/PACKAGE•©Documented?指定被修饰的该Annotation可以被javadocI具提取成文档.•©Inherited?指定被修饰的Annotation将具有继承性如果某个类使^@Xxx注解(该Annotation使用了©Inherited修饰)修饰,则其子类口动被@乂乂灭注解修饰.Annotation/***Createdbyjifangon15/12/22.*/@Tnherited@Target({ElementType.ANNOTATION_TYPE,ElementType.TYPE})©Retention(RetentionPolicy.RUNTIME)public©interfaceTestable{}ClientpublicclassClient{ @Testpublicvoidclicnt(){newSubClass();©TestableclassSupperClass{}classSubClassextendsSupperClass{publicSubClass(){for(Annotationannotation:SubClass,class.getAnnotations()){System・out.printin(annotation);}自定义注解•根据Annotation是否包含成员变量,可以把Annotation分为两类:o标记Annotation:没冇成员变量的Annotation;这种Annotation仅利川自身的存在与否来提供信息;o元数据Annotation:包含成员变量的Annotation;它们可以接受(和捉供)更多的元数据;•定义新注解使用©interface关键字,其定义过程与定义接口非常类似(见上面的©Testable),需要注意的是:Annotation的成员变量在Annotation定义中是以无参的方法形式来声明的,其方法名和返回值类型定义了该成员变量的名字和类型,而且我们还可以使用default关键字为这个成员变量设定默认值.©Inherited©Retention(RetentionPolicy.RUNTIME)@Target({ElementType.METHOD,ElementType.TYPE})public@intcrfaccTag{Stringname()default该叫啥才好呢?“;Stringdescription()default〃这家伙很懒,啥也没留下・・・ •口定义的Annotation继承了Annotation这个接口,因此口定义注斛中包含了Annotation接口中所有的方法;publicinterfaceAnnotation{/***@returntrueifthespecifiedobjectrepresentsanarmotation*thatislogicallyequivalenttothisone,othcrwisefalse*/booleanequals(Objectobj);/***@rcturnthehashcodeofthisannotation*/inthashCode();/***@rcturnastringrepresentationofthisannotation*/StringtoStringO;/***Returnstheannotationtypeofthisannotation.*/Classimplementsjava・io.Serializable,java.lang,reflect.GenericDeclaralion,java.lang,reflect・Type,java・lang・reflcct・AnnotatcdElcment{publicinterfaceAnnotatedElement{ /***Returnstrueifanannotationforthespecifiedtype*ispresentonthiselement,elsefalse.Thismethod*isdesignedprimarilyforconvenientaccesstomarkerannotations.*/boolcanisArmotationProsent(Class〈?cxtcndsArmotation>annotationClass);/***Returnsthiselement'sarmotationforthespecifiedtypeif*suchanemnoteitionisprosent,elsenull.*/TgetAnnotation(ClassannotationClass);/***Rcturnsallemnotationsprosentonthisclement.*/Annotation[]getAnnotations();/***Rcturnsallemnotationsthatarcdirectlyprosentonthis*element.Unliketheothermethodsinthisinterface,thismethod*ignoresinheritedannotations.(Returnsanarrayoflengthzero辻*noannotationsaredirectlypresentonthiselement.)Thecallerof*thismethodisfreetomodifythereturnedarray;itwillhaveno*effectonthearraysreturnedtoothercallers.*/Annotation[]getDeclaredAnnotations();}这样,我们只需要获取到Class?Method?Filed等这些实现了AnnotatedElement接口的类实例,就可以获取到我们想要的注解信息了./***Createdbyjifangon15/12/22.*/publicclassClient{@Testpublicvoidclient()throwsNoSuchMethodException{Annotation[]annotations二this.getClass().hod(〃client〃)•^etAnnotations();for(Armoteitionarmotation:emnotations){System・out.printin(annotation.annotationType().getName()); 如果需要获取某个注解屮的元数据,则需要强转成所需的注解类型,然后通过注解对象的抽象方法來访问这些元数据:@Tag(name二〃client〃)publicclassClient{©Testpublicvoidclient()throwsNoSuchMethodException{Annotation[]annotations二this.getClass().getAnnotations();for(Annotationannotation:annotations){if(armotationinstemccofTag){Tagtag=(Tag)annotation;System.out.printIn("name:"+tag.name());System,out.println("description:"+tag.description());}}}}模拟Junit框架我们用©Testable标记哪些方法是可测试的,只有被©Testable修饰的方法才可以被执行./***Createdbyjifangon15/12/27.*/©Inherited©Target(ElementType.METHOD)©Retention(RetentionPolicy.RUNTIME)public©interfaceTestable{如下定义TestCase测试用例定义了6个方法,其中有4个被©Testable修饰了:publicclassTestCase{©Testablepublicvoidtestl(){System・out.printin(〃testl〃);}publicvoidtest2()throwsIOExccption{System,out.println(z,test2zz);thrownewIOException(,z我test2出错啦・・・〃);}©Testablepublicvoidtest3(){System・out.println(〃test3〃);thrownewRuntimeException(,z我test3出错啦•••〃);} publicvoidtest4(){System・out.println(〃test4〃);}©Testablepublicvoidtest5(){System・out.println(〃test5〃);}©Testablepublicvoidtest6(){System・out.println(〃test6〃);}}为了让程序中的这些注解起作用,必须为这些注解提供一个注解处理工具./***Createdbyjifangon15/12/27.*/publicclassTestab1eProcessor{ publicstaticvoidprocess(Stringclazz)throwsClassNotFoundException,IllegalAccessException,InstantiationException{intpassed二0;intfailed=0;Objectobj=Class.forName(clazz).newlnstance();for(Methodmethod:Class.forName(clazz).getMethods()){if(method.isAnnotationPresent(Testable,class)){try{method.invokc(obj);++passed;}catch(IllegalAccessExceptionInvocationTargetExceptione){System.out.println(〃method"+method.getName()+〃executeerror:〈〃+c.gctCause()+">“);e.printStackTrace(System,out);++failed;}}}System,out.printin(,z共运行〃+(failed+passed)+〃个方法,成功〃+passed+〃个,失败〃+failed+〃个“);}publicstaticvoidmain(String[]args)throwsClassNotFoundException,InstantiationException,IllegalAccessException{TestableProcessor,process(/zcom.feiqing.annotation.TestCase〃);}抛岀特立异常前面介绍的只是一个标记Annotation,程序通过判断Annotation是否存在来决定是否运行指定方法,现在我们要针对只在抛出特殊异常时才成功添加支持,这样就用到了貝有成员变量的注娜:/***Createdbyjifangon15/12/28.*/@Tnherited@Target(ElemcntTypc.METHOD)©Retention(RetentionPolicy.RUNT1ME)public©interfaceTestableException{Class[]value(); }•TestCase/***Createdbyjifangon15/12/27.*/publicclassTestCase{publicvoidtestl(){System,out.println(〃tcstl〃);}©TestableException(ArithineticException.class)publicvoidtest2()throwsTOException{inti=1/0;System,out.println(i);}@TestableException(ArithmeticException.class)publicvoidtest3(){System,out.println(z,test3,/);thrownewRuntimeException(/z我test3岀错啦•••〃);}publicvoidtest4(){System,out.println(z,test4,z);}@TestableException({ArithmeticException.class,IOExccption.class})publicvoidtest5()throwsFileNotFoundException{FilelnputStreamstream=newFilelnputStream(/zxxxxz/);}©Testablepublicvoidtest6(){System・out.println(〃test6〃);注解处理器 publicclassTcstoblcExccptionProcessor{publicstaticvoidprocess(Stringclazz)throwsClassNotFoundException,IllegalAccessException,InstantiationException{intpassed二0;intfailed=0;Objectobj=Class.forName(clazz).newlnstance();for(Methodmethod:Class.forName(clazz).getMethods()){if(method,isAnnotationPresent(TestobleException.class)){try{method,invoke(obj,null);//没有抛岀异常(失败)++failed;}catch(TnvocationTargetExceptione){//获取异常的引发原因Throwablecause=e.getCause();intoldPassed二passed;for(ClassexcType:method.gctArmot3tion(TcstoblcExccption・class).value()){//是我们期望的异常类型之一(成功)if(excType.islnstance(cause)){++passed;break;}}//并不是我们期望的异常类型(失败)if(oldPassed二二passed){++failed;System,out.printf(,zTcst<%s>failed<%s>%n,z,method,e);}}}}System,out.printin共运行〃+(failed+passed)+"个方法,成功"+passed+"个,失败"+failed+"个");}publicstaticvoidmain(String[]args)throws11lcgalAcccssExccption,InstantiationException,ClassNotFoundException{process(/zcom・feiqing.annotation.TestCnse"); 注解添加监听器下面通过使用Annotation简化事件编程,在传统的代码中总是需要通过addActionListcncr方法來为事件源绑定事件监听器:/***Createdbyjifangon15/12/27・*/publicclassSwingPro{privateJFramcmainWin=newJFrame(z,使用注解绑定事件监听器”);privateJButtonok=newJButton(〃确定〃);privateJButtoncancel二newJButton(〃取消〃);publicvoidinit(){JPaneljp=newJPanel();//为两个按钮设置监听事件ok.addActionListener(newOkListener());cancel.addActionListencr(ncwCancclListcncr());jp.add(ok);jp.add(cancel);mainWin.add(jp);mainWin.sctDcfaultCloscOpcration(JFramc.EXIT_ON_CLOSE);mainWin.pack();mainWin.setVisible(true);}publicstaticvoidmeiin(String[]args){newSwingProO.init();}}classOkListcncrimplcmcntsActionListencr{©OverridepublicvoidactionPerformed(ActionEvente){JOptionPane.showMessageDialog(nul1,〃你点击了确认按钮!〃);classCancelListenerimplementsActionListener{ ©OverridepublicvoidactionPerformed(ActionEvcntc){JOptionPane.showMessageDia1og(nu11,〃你点击了取消按钮!");}}下面我们该用注解绑定监听器:•首先,我们需耍口定义一个注解/***Createdbyjifangon15/12/27.*/©Inherited@Target(ElementType.FIELD)©Retention(RctcntionPolicy.RUNTIME)public©interfaceActionListenerFor{Classlistener=field.getAnnotation(ActionListenerFor.class).listener();//添加到成员变量中targetButton.addActionListener(listener,newlnstance());}}}}•主程序(注意注释处)publicclassSwingPro{privateJFramemainWin=newJFrame(,z使用注解绑定事件监听器〃);/***使用注解设置Listener*/©ActionListenerFor(listenet二OkListener.class)privateJButtonok二newJButton(〃确定〃);@ActionListenerFor(listener=CancelListener.class)privateJButtoncancel=newJButton(〃取j肖〃);publicSwingProinit(){JPancljp二newJPancl();//使得注解生效try{ActionListenerTnstaller.instal1(this);}catch(IllegalAcccssExccption|InstaritiationExccptionc){e.printStackTrace(System,out);}jp.add(ok);jp.add(canccl);mainWin.add(jp);mainWin.setDefaultCloseOperation(JFrame.EXIT_0N_CL0SE);mainWin.pack();mainWin.setVisible(true);returnthis; 〃下同mainmai谕定取消2(truereturnthis;pur消息你点击了備认按钮!确定重复注解在Java5至ljJava7这段时间里,同一个程序元素前只能使用一个相同类型的Annotation;如果需要在同一个元素前使用多个相同的Annotation,则必须使用AnnotationJava8对这种情况做了改善,但其实也只是种写法上的简化,其本质还是一样的).曲于在实际开发中,Java8还未大面积的使用,因此在此只介绍Java7中重复注解定义与使用.•TableAnnotation定义(代表数据库表)/***Createdbyjifangon15/12/27.*/©Inherited©Retention(RetentionPolicy.RUNTIME)public@interfaceTable{Stringname()default"表名是啥?“;Stringdescription()default〃这家伙很懒,啥也没留下・・・〃 •Table容器©Inherited©Retention(RetentionPolicy.RUNTIME)public@inlerfaceTables{Tablet]value();}注意:?容器注解的保留期必须比它所包含的注解的保留期更长,否则JVM会丢弃容器,相应的注解也就丢失了.•Client使用时需要用Table容器来盈袈「Table注解©Tables({@Table(name二user",description二〃用户表“),@Table(name二气_feed〃,description二〃动态表")})"publicclassClient{©Testpublicvoidclient(){TablestableArray=this・getClass()・getAnnotation(Tables・class);Tablet]tables=tableArray.value();for(Tabletable:tables){System.out.printin(table.name()+":"+tablc.description());}}}在Java8中,可以直接使用©Table(name="t_userz,,description="用户表")@Table(name="t_feecT,description="动态表〃)的形式來注解Client,但@Tables还是需要开发者來写的,由此可以看出,重复注解只是一种简化写法,这种写法只是一种假象:多个重复注解其实会被作为容器注解的value成员.参考:EffectiveJava 疯狂Java讲义Java核心技术

当前文档最多预览五页,下载文档查看全文

此文档下载收益归作者所有

当前文档最多预览五页,下载文档查看全文
温馨提示:
1. 部分包含数学公式或PPT动画的文件,查看预览时可能会显示错乱或异常,文件下载后无此问题,请放心下载。
2. 本文档由用户上传,版权归属用户,天天文库负责整理代发布。如果您对本文档版权有争议请及时联系客服。
3. 下载前请仔细阅读文档内容,确认文档内容符合您的需求后进行下载,若出现内容与标题不符可向本站投诉处理。
4. 下载文档时可能由于网络波动等原因无法下载或下载错误,付费完成后未能成功下载的用户请联系客服处理。
关闭