版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
JAVA高级特性1第六章
泛型和注解2回忆Class对象提供了大量访问类的内部结构的方法。如何访问这些信息?java.lang.reflect包还提供了用于动态代理的类和接口分别是什么?如何使用CGLIB实现动态代理模式?3本章内容Annotation的概念和作用根本注解、元注解和自定义注解提取注解信息定义泛型接口、泛型类、泛型方法类型通配符和通配符限定擦除4理解java注解的概念和作用掌握注解的使用掌握提取注解信息掌握泛型的使用掌握通配符的使用本章目标5根本注解@Override:指定方法重写,强制一个子类必须重写父类的方法。只能作用于方法,不能作用于其他元素。@Deprecated:用于标记某个程序元素已过时,当其他程序使用已过时的类、方法时,编译器将会给出警告@SuppressWarnings:抑制编译器警告。6根本注解强制子类重写父类方法,如果没有重写会出现编译错误publicclassPerson{ publicvoidinfo(){ System.out.println("这是Person类的对象"); }}publicclassStudentextendsPerson{ @Override publicvoidinfo(){ System.out.println("这是Student类的对象"); }}7根本注解被@Deprecated修饰的方法会出现过时标记,即方法名上出现一条删除线
@Deprecated publicvoidpaly(){ System.out.println("这个方法已过时");
}8根本注解在程序中使用没有泛型限制的集合将会引起编译器警告,可以使用@SuppressWarnings忽略警告
@SuppressWarnings("unchecked")
classSuppressWaringsTest{ publicstaticvoidmain(String[]args){ List<String>list=newArrayList(); }
}9元注解除了三个根本注解之外,java还提供了四中元注解,元注解专职负责注解其他注解10元注解@Target可用的ElementType参数包括:11元注解@Retention可选的RetentionPolicy参数包括:12自定义注解定义新的Annotation类型使用@interface关键字语法:例如:[元注解]public@interface注解名称{[成员变量]}public@interfaceMyAnnotation{}上面代码定义一个注解MyAnnotation,该注解默认保存在class文件中,可用于修饰程序中的类、方法、变量、接口等的定义。13自定义注解我们根据Annotation是否包含成员变量,可以把Annotation分为两类:标记Annotation和元数据Annotation。标记Annotation:一个没有成员定义的Annotation类型被称为标记。这种Annotation仅使自身的存在与否来为我们提供信息。如@Override等。元数据Annotation:那些包含成员变量的Annotation,因为他们可以接受更多的元数据,所以也被称为元数据Annotation。14自定义注解定义带成员变量的Annotation例如:@Retention(RetentionPolicy.RUNTIME)//指定该注解为运行时注解public@interfaceMyAnnotation{ Stringname(); intage();}publicclassStudent{ @MyAnnotation(name="张飞",age=18) publicvoidinfo(){}}@Retention(RetentionPolicy.RUNTIME)public@interfaceMyAnnotation{ Stringname()default"张三"; intage()default18;}给成员变量指定默认值15提取注解信息AnnotatedElement接口是所有程序元素〔如Class、Method〕的父接口,程序通过反射获取了某个类的AnnotatedElement对象之后,就可以通过该对象的方法来访问Annotation信息。classDemo{ publicstaticvoidmain(String[]args){ Studentstudent=newStudent(); try{ Annotation[]aArray=student.getClass().getMethod("info").getAnnotations(); for(Annotationan:aArray){ System.out.println(an); } }catch(Exceptione){ e.printStackTrace(); } }}16提取注解信息如果我们需要获取某个注解里的元数据,那么可以将注解类型强制转换成所需的注解类型,然后通过注解对象的抽象方法来访问这些元数据。例如:publicstaticvoidmain(String[]args){Studentstudent=newStudent();try{ Annotation[]aArray=student.getClass().getMethod("info").getAnnotations(); for(Annotationan:aArray){
//判断注解类型
if(aninstanceofMyAnnotation){
System.out.println("Annotationis:"+an); //将注解类型强制转换为MyAnnotation
System.out.println("():"+((MyAnnotation)an).name());
System.out.println("an.age():"+((MyAnnotation)an).age()); } }}catch(Exceptione){ e.printStackTrace();}}17泛型Java的集合有个缺点:当我们把一个对象“丢进”集合里后,集合就会“忘记”这个对象的数据类型,当再次取出该对象时,该对象的编译类型就变成了Object类型。为了解决这个问题,从JDK1.5以后,Java引入了“参数化类型〔parametrizedtype〕”的概念,允许我们在创立集合时指定集合元素的类型。如List<String>,这说明该List集合只能保存字符串类型的对象。Java的参数化类型被称为泛型〔Generic〕。18定义泛型接口、类泛型允许在定义接口、类时指定类型形参,类型形参在整个接口、类中可当成类型使用。//定义接口时指定类型形参:EpublicinterfaceList<E>{ //在接口中,E可以作为类型使用 voidadd(Ee); Iterator<E>iterator();}19定义泛型接口、类当我们使用List类型时,为形参E传入String类型实参,那么产生了一个新的类型:List<String>类型,我们可以把List<String>想象成E被替换成String的特殊List子接口:程序虽然定义了一个List<E>接口,但实际使用时可以产生无数多个List接口,只要为E传入不同的类型参数,系统就会多出一个新的List子接口注意:“ListString”只是逻辑上存在,物理上并不存在。publicinterfaceListStringextendsList{ //原来的形参E全部变成String类型实参 voidadd(Strings); Iterator<String>iterator();}20定义泛型接口、类publicclassApple<T>{ privateTinfo;//T可以作为类型在类中使用 publicApple(){} publicApple(Tinfo){ =info; } publicTgetInfo(){ returninfo; } publicvoidsetInfo(Tinfo){ =info; } publicstaticvoidmain(String[]args){ //如果传递给T的实参是String类型,所以构造器的参数只能是String Apple<String>a1=newApple<String>("苹果"); System.out.println(a1.getInfo()); //如果传递给T的实参是Double类型,所以构造器的参数只能是Double Apple<Double>a2=newApple<Double>(5.6); System.out.println(a2.getInfo()); }}构造器不要增加泛型声明21定义泛型接口、类当创立了带泛型声明的接口、父类之后,可以为该接口创立实现类,或从该父类派生子类,但是当使用这些接口、父类时不能再包含类型参数。例如下面的代码就是错误的:这就好比我们定义方法的时候可以使用形参,但调用方法时必须传入实参。所以我们需要把上面代码的T换成实际类型。上面的代码应改为:classAextendsApple<T>{}classAextendsApple<String>{}//传入String类型classAextendsApple{}//不传入实际参数也正确22深入泛型当我们使用一个泛型类时,应该为这个泛型类传入一个类型实参,如果没有传入实参,就会引起泛型警告publicvoidtest(Listc){ for(inti=0;i<c.size();i++){ System.out.println(c.get(i)); }}泛型警告23类型通配符为了表示各种泛型List的父类,我们需要使用类型通配符,类型通配符是一个问号“?”,将一个问号作为类型实参传给List集合,写作:List<?>〔意思是未知类型元素的List〕。这个?被称为通配符,它可以匹配任何类型。List<?>是任何泛型List的父类型publicvoidtest(List<?>c){ for(inti=0;i<c.size();i++){ System.out.println(c.get(i)); }}类型通配符24类型通配符上限当直接使用List<?>这种形式时,即说明这个List集合可以是任何泛型List的父类。但还有一种特殊的情形,我们只想表示它是某一类泛型的父类例如:publicabstractclassShape{ publicabstractvoiddraw(Canvasc);}classCircleextendsShape{ publicvoiddraw(Canvasc){ System.out.println("在画布上画一个圆"); }}classRectangleextendsShape{ publicvoiddraw(Canvasc){ System.out.println("在画布上画一个矩形"); }}classCanvas{ publicvoiddrawAll(List<Shape>shapes){ for(Shapes:shapes){ s.draw(this); } } publicstaticvoidmain(String[]args){ List<Circle>circleList=newArrayList<Circle>();
circleList.add(newCircle()); Canvasc=newCanvas(); c.drawAll(circleList); }}List<Circle>并不是List<Shape>的子类,编译错误!25类型通配符上限为了解决上述问题,可以修改代码如下:通配符可以保证编译通过,但带来了类型平安问题classCanvas{ publicvoiddrawAll(List<?>shapes){ for(Shapes:shapes){ s.draw(this); } } publicstaticvoidmain(String[]args){ List<Circle>circleList=newArrayList<Circle>();
circleList.add(newCircle()); Canvasc=newCanvas(); c.drawAll(circleList); }}使用通配符,表示任意类型如果传递进来的不是Shape,会发生类型转换异常问题26类型通配符上限实际上,我们需要一种泛型表示方法,它可以表示所有Shape泛型List的父类而不是所有泛型List的父类。为了满足这种需求,Java泛型提供了被限制的通配符语法:List<?extends被限制的类型名称>publicvoiddrawAll(List<?extendsShape>shapes){ for(Shapes:shapes){ s.draw(this); }}泛型信息匹配Shape的子类27泛型方法JDK1.5还提供了泛型方法的支持。例如:将一个Object数组的所有元素添加到一个Collection集合中。类型通配符在这里是不适用的,因为无法将对象添加到不知道具体类型的集合中staticvoidfromArrayToCollection(Object[]objs,Collection<Object>c){ for(Objecto:objs){ c.add(o); }}只能添加Object类型,不能添加其他类型28泛型方法语法:修改前面代码:与接口、类定义的类型形参相比,泛型方法定义的类型形参只能在方法内部使用修饰符<T,S>返回值类型方法名〔形参列表〕{}static<T>voidfromArrayToCollection(T[]a,Collection<T>c){ for(To:a){ c.add(o); }}29泛型方法前面代码编译器根据实参可以推断出最直接的类型形参的类型。为了让编译器能够准确的推断出泛型方法中类型形参的类型,不要制造迷惑!
static<T>voidtest(Collection<T>a,Collection<T>b){ for(To:a){ b.add(o); } } publicstaticvoidmain(String[]args){ List<Object>objList=newArrayList<Object>(); List<String>strList=newArrayList<String>(); //这里将发生编译错误 test(strList,objList);
}
static<T>voidtest(Collection<?extendsT>a,Collection<T>b){ for(To:a){ b.add(o); } } publicstaticvoidmain(String[]args){ List<Object>objList=newArrayList<Object>(); List<String>strList=newArrayList<String>(); test(strList,objList); }通配符限定30类型通配符下限前面所使用的test方法可以将集合a中的元素复制到集合b,假设该方法还需要一个返回值,返回最后一个被复制的元素,修改该方法如下:static<T>Ttest(Collection<?extendsT>a,Collection<T>b){ Tlast=null; for(To:a){ last=o; b.add(o); } returnlast;}publicstaticvoidmain(String[]args)
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2024万科物业合同范本涉及社区垃圾分类与回收利用3篇
- 2024年度托管班教师信息技术应用能力提升聘用合同3篇
- 2024乌鲁木齐房屋租赁合同:租客租后维修责任协议3篇
- 2024年地毯新产品推广营销合同范本3篇
- 新疆警察学院《测控系统设计基础训练》2023-2024学年第一学期期末试卷
- 人教版凡尔赛-课件
- 2024年二级造价师考试题库带答案1
- 公司签居间合同范例
- 打桩地基施工合同范例
- 销售卖货合同范例
- 24春国家开放大学《乡镇行政管理》作业1-5参考答案
- 2024年激光切割机市场需求分析报告
- 西餐原料知识理论知识考核试题及答案
- 加油站员工绩效考核(标准版)
- 2024年国家开放大学(电大)-国家开放大学(国学经典选读)笔试历年真题荟萃含答案
- 自动泊车系统的使用说明
- 文言文阅读训练:曾巩《隆平集-何承矩》(附答案解析与译文)
- 《路德维希·费尔巴哈和德国古典哲学的终结》导读
- 材料分拣plc控制系统设计
- 应用经方治疗顽固性心力衰竭课件
- 金刚石切割线行业报告
评论
0/150
提交评论