第6章 Java语言新特性_第1页
第6章 Java语言新特性_第2页
第6章 Java语言新特性_第3页
第6章 Java语言新特性_第4页
第6章 Java语言新特性_第5页
已阅读5页,还剩26页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、第第6 6章章 JavaJava语言新特性语言新特性6.1 枚举枚举6.2 注解注解6.3 Lambda表达式表达式6.1 6.1 枚举枚举6.1.1 定义枚举类型定义枚举类型Java SE 5.0引入一个新的关键字enum表示枚举类型。定义一个枚举类型很简单,下面是一个枚举类型的示例。public enum Season SPRING, SUMMER, AUTUMN, WINTER;上面创建了一个名为Season的枚举类型,它有4个成员。由于枚举类型的实例是常量,因此按命名习惯它们都用大写字母表示。为了使用enum,需要创建一个该类型的引用,并将其赋值给某个实例。例如:Season seas

2、on = Season.SUMMER;6.1.1 6.1.1 定义枚举类型定义枚举类型在创建一个enum的实例后,编译器会自动创建一些有用的方法。ordinal()方法用来返回某个特定enum常量的索引;values()方法用来按照enum常量的声明顺序产生由这些常量值构成的数组。例如:for (Season season : Season.values() System.out.println(season+,ordinal +season.ordinal();输出SPRING, ordinal 0SUMMER, ordinal 1AUTUMN, ordinal 2WINTER, ordin

3、al 36.1.1 6.1.1 定义枚举类型定义枚举类型【例6.1】用enum模拟交通信号灯。程序运行结果:The traffic light is REDThe traffic light is GREENThe traffic light is YELLOWThe traffic light is REDThe traffic light is GREENThe traffic light is YELLOWThe traffic light is RED6.1.2 enum6.1.2 enum构造方法构造方法枚举像类一样也可以有构造方法,这样在定义其成员变量时就可以用构造方法来进行初始化

4、。在定义枚举时,必须将枚举常量定义在最前面,并以分号“;”与其他成员隔开。若enum是public类型且在类外部定义,则文件名必须与enum的名字相同,且文件中不能再定义其他public类型的类。【例6.2】在enum中定义它的构造方法和普通方法。程序运行结果:shanghaishenzhenxianBeijing6.1.3 6.1.3 使用使用EnumMapEnumMapEnumMap是一种特殊的Map(将在第7章介绍),它要求所有的键(Key)都必须来自同一个枚举,该枚举在创建EnumMap时显式或隐式地指定。EnumMap在内部表示为数组,这种表示形式非常紧凑且高效,故可放心地使用enu

5、m实例在EnumMap中进行查找。不过,只能将enum实例作为键来调用put()方法,其他操作与使用一般的Map差不多。【例6.3】通过使用EnumMap的键对象来取得值对象。程序运行结果:3640423640426.2 6.2 注解注解在程序中使用注解的优点有:l提供了一种结构化的、且具有类型检查能力的新途径,以编写更为健壮的代码。l通过使用注解,程序员可以在不改变源程序逻辑的情况下为代码加入元数据。l用于附属文件的自动生成,例如部署描述符或bean信息类。l用于测试、日志、事务语义等代码的生成。l按产生方式和功能的不同,Java程序的注解可分为内置注解、自定义注解和元注解。6.2.1 6.

6、2.1 内置注解内置注解内置注解是指Java语言内部已定义好的注解,可直接使用。Java SE 5.0预定义了3种标准注解(在java.lang包中),如下:lOverride:表示当前的方法将重写父类中的方法。如果不小心拼写错误或者签名对不上父类的方法,编译器就会发出错误提示。lDeprecated:表示某个程序元素(类、方法等)已过时。当其他程序使用已过时的类、方法时,编译器将会发出警告。lSuppressWarnings:关闭指定的编译器警告信息。6.2.1 6.2.1 内置注解内置注解1OverrideOverride告诉编译器某个方法必须重写父类中的方法,编译器得知后,在编译程序时如

7、果发现该方法并非是重写的父类方法,就会报错。该注解只能应用于方法。【例6.4】使用Override注解。程序运行结果:false6.2.1 6.2.1 内置注解内置注解这显然是不对的。现在对Equals()方法加上Override注解,要求编译器必须检查这个方法究竟是不是重写父类的某个方法,编译器通过检查发现父类Object中其实并没有这个方法,于是报错。Eclipse在用户编辑代码的阶段就直接显出错误提示,如图6.1所示。6.2.1 6.2.1 内置注解内置注解【例6.5】使用Deprecated注解。DeprecatedTest.javapackage org.annotations;pu

8、blic class DeprecatedTest extends Service Overridepublic void doSomething() System.out.println(do something in DeprecatedTest class);public static void main(String args) DeprecatedTest sub = new DeprecatedTest();sub.doSomething();class Service Deprecatedpublic void doSomething() System.out.println(d

9、o something);6.2.1 6.2.1 内置注解内置注解说明:程序中有一个Service类,其中定义了doSomething()方法,经过一段时间之后,考虑不建议使用这个方法,因而将它注解为Deprecated。DeprecatedTest类试图在继承这个类后重新定义doSomething()方法,程序编译时就会出现如图6.2所示的警告信息。但是含有标记Deprecated的类仍然可以被JVM执行。程序运行结果为:do something in DeprecatedTest class6.2.1 6.2.1 内置注解内置注解3SuppressWarningsSuppressWarni

10、ngs用于有选择地关闭编译器对类、方法、成员变量、变量初始化的警告,这类警告并不一定表示程序错误。例如,当使用一个容器类又没有提供它的类型时,编译器将发出“unchecked warning”警告,通常这种情况需要查看引起警告的代码,若它真的错了当然要纠正;但有时代码并无错,又无法避免这种警告,此时SuppressWarnings就派上用场了,在调用的方法前增加该注解告诉编译器停止对此方法的警告。下面的方法f()中定义了一个ArrayList类,但同时会出现警告信息。public void f() List list = new ArrayList(); list.add(hello);警告信

11、息表示List类必须使用泛型才是安全的,为消除警告须将这个方法作如下改写:public void f() List list = new ArrayList();list.add(hello);6.2.1 6.2.1 内置注解内置注解但如果实际的程序并无很高的安全需求,如此写法就显得烦冗,可又不想看到警告信息,于是使用SuppressWarnings注解,如下:SuppressWarnings (value = unchecked)public void f() List list = new ArrayList();list.add(hello);与Override和Deprecated注解

12、不同,SuppressWarnings有一个类型为String的元素。注解的语法允许在注解名后跟括号,括号中是使用逗号分隔的“name = value”对,用来为注解的成员赋值。按照约定,单一元素(只有一个元素)的名字建议取为“value”,而这里SuppressWarnings类型只定义了一个单一成员,故只有一个简单的“value = .”作为“name = value”对,这种情况还可更进一步省去“value =”,例如:SuppressWarnings(unchecked,deprecation)由于成员值是一个数组,故使用大括号来声明数组值。当SuppressWarnings所声明的被

13、禁止警告个数为1时,还可省去大括号,如下:SuppressWarnings(unchecked)6.2.1 6.2.1 内置注解内置注解【例6.6】使用SuppressWarnings注解。SuppressWarningsTest.javapackage org.annotations;import java.util.*;import java.time.*;public class SuppressWarningsTest SuppressWarnings(unchecked)public static void main(String args) Map map = new TreeMa

14、p();map.put(hello, LocalDateTime.now();System.out.println(map.get(hello);List list = new ArrayList();list.add(annotation);System.out.println(list);程序运行结果:2015-05-12T11:14:27.795annotation6.2.2 6.2.2 自定义注解自定义注解Java语言本身提供的注解并不多,但它有一个强大的机制给用户自定义注解。现实中程序员更多的是使用开发环境或IDE定义的注解,它们数量众多、功能强大,是编程的有力工具。注解类型的定义可

15、看作是一种特殊的接口定义,只是在interface关键字前加了一个符号。编译器在编译注解的定义时,会自动从java.lang.annotation.Annotation接口继承该注解,故不必(也不允许)在注解定义语句后边再加extends子句。可以按如下方式使用自定义的注解MyAnnotation:MyAnnotation(id = 12, value = java) public void f() 6.2.3 元注解Java 8在java.lang.annotation包下提供了6个元注解,具体如下。l Target:指定被修饰的注解能用于哪些程序元素类型。其参数ElementType表示所

16、适用的元素类型,取值有:CONSTRUCTOR(构造器)、FIELD(成员变量)、LOCAL_VARIABLE(局部变量)、METHOD(方法)、PACKAGE(包)、PARAMETER(参数)、TYPE(类、接口、注解类型或枚举),以及ANNOTATION_TYPE(标准注解)。l Retention:指定被修饰注解的保存级别。其参数RetentionPolicy表示保存级别,取值有:SOURCE(只保留在源代码中,编译器直接丢弃这种注解)、CLASS(保存在class文件中,但运行时JVM不可获取注解信息)、RUNTIME(保存在class文件中且运行时JVM也可获取注解信息),默认保存级

17、别为CLASS。l Documented:指定被修饰的注解将被javadoc工具提取成文档。l Inherited:指定被修饰的注解(这里假设为Xxx)具有继承性,即如果某个类使用了Xxx注解,则其子类也将自动被Xxx修饰。l Repeatable:用于定义Java 8新增的重复注解。6.2.3 元注解1TargetTarget描述了被修饰注解所适用的程序元素的种类。当一个注解没有被Target修饰时可适用于所有的程序元素;而当存在Target时编译器会强制实施指定的类型限制。例如:Target(ElementType.METHOD) interface MyAnnotation MyAnno

18、tation / 不正确,不能为类注解public class Comment MyAnnotation / 正确,可以为方法注解public void method()6.2.3 元注解2RetentionRetention定义了注解信息被保留的时间长短,支持三种不同保存级别,写法如下:/* 只保留在源代码中,被编译器丢弃 */Retention(RetentionPolicy.SOURCE) interface MyAnnotation1 /* 保存在class文件中,但JVM无法获取 */Retention(RetentionPolicy.CLASS) interface MyAnnot

19、ation2 /* 保存在class文件中,且JVM可以获取 */Retention(RetentionPolicy.RUNTIME) interface MyAnnotation3 6.2.3 元注解3DocumentedDocumented注解和它的名字一样与文档有关。在默认情况下使用javadoc或其他类似工具自动生成文档时,源程序中的注解将被忽略掉。如果想在文档中也包含注解,就必须使用Documented修饰想要包含的注解。4InheritedInherited表示注解类型会被自动继承。当一个使用Inherited修饰的注解被用于一个类时,它也将被自动地用于该类的所有子类。例如:Inh

20、erited interface MyAnnotation MyAnnotationpublic class ParentClass public class ChildClass extends ParentClass 在以上代码中,ChildClass和ParentClass一样都已被MyAnnotation注解了。6.2.3 元注解【例6.7】使用元注解读取MyTest类的信息。程序运行结果:output somethingbeijingshanghai6.3 Lambda6.3 Lambda表达式表达式6.3.1 Lambda表达式简介表达式简介首先看一个最简单的lambda表达式,它

21、的计算结果是一个常量值,如下:()-274.83这个lambda表达式没有参数,所以参数列表为空,它返回常量值274.83。因此,这个表达式的作用类似于下面的方法:double myVal() return 274.83; 当然,lambda表达式定义的方法没有名称。当lambda表达式需要参数时,就要在操作符左侧的参数列表中加以指定。下面是一个简单的例子:(value)-(value % 2) = 0如果参数value的值是偶数,这个lambda表达式会返回true。6.3.2 6.3.2 函数式接口函数式接口(1)定义和使用函数式接口定义和使用函数式接口定义函数式接口只能为其声明一个方法,

22、例如:public interface MyVal double getValue();其中,getValue()方法隐式地是抽象方法且是MyVal定义的唯一方法。6.3.2 6.3.2 函数式接口函数式接口下面通过一个例子来说明如何在参数上下文中使用lambda表达式。首先,声明对函数式接口MyVal的一个引用:MyVal myVal;接下来,将一个lambda表达式赋给该引用:myVal = ()-274.83;当目标类型上下文中出现lambda表达式时,会自动创建实现了函数式接口的一个类的实例,函数式接口声明的抽象方法的行为由lambda表达式定义。当通过目标调用该方法时就会执行lamb

23、da表达式。可见,lambda表达式提供了一种将代码段转换为对象的方式。上例中的lambda表达式成了getValue()方法的实现。因此,下面的代码执行将显示274.83:System.out.println(myVal.getValue();6.3.2 6.3.2 函数式接口函数式接口【例6.8】使用lambda表达式实现自定义函数式接口。MyIntPredicate.javapackage org.lambda;FunctionalInterface/ Java 8新增注解,指定检查该接口必须是函数式接口public interface MyIntPredicate / 自定义的函数式接

24、口boolean test(int value);/ 唯一(只能有一个!)的抽象方法6.3.2 6.3.2 函数式接口函数式接口LambdaDemo.javapackage org.lambda;public class LambdaDemo public static void main(String args) int n = Integer.parseInt(args0);MyIntPredicate isEven = (value)-(value % 2) = 0;/ 用lambda表达式实现接口if(isEven.test(n)/ 调用接口方法返回值判断奇偶数System.out.p

25、rintln(n + 是偶数);elseSystem.out.println(n + 是奇数);用第2章介绍的操作方法(见图2.1)打开“Run Configurations”窗口,配置程序运行时的输入参数,在“Arguments”标签页的“Program arguments”栏输入“144”,然后单击“Run”按钮运行程序,结果为:144是偶数6.3.2 6.3.2 函数式接口函数式接口(2)使用使用Java 8预定义的接口预定义的接口Java 8在java.util.function包下预定义了大量函数式接口,典型地包含如下4类。lXxxFunction:这类接口中通常包含一个apply(

26、)抽象方法对参数进行处理、转换(apply()方法的处理逻辑由lambda表达式来实现),然后返回一个值。lXxxConsumer:这类接口中通常包含一个accept()抽象方法,它与XxxFunction接口的apply()方法基本相似,也负责对参数进行处理,只是该方法不会返回处理的结果。lXxxxPredicate:这类接口中通常包含一个test()抽象方法,该方法用来对参数进行某种判断(其判断逻辑也由lambda表达式实现),然后返回一个boolean值。lXxxSupplier:这类接口中通常包含一个getAsXxx()抽象方法,此方法不需要输入参数,它会按某种逻辑算法(算法当然也是l

27、ambda表达式实现的)返回一个数据。6.3.2 6.3.2 函数式接口函数式接口【例6.9】用Java 8预定义的函数式接口实现奇偶数判断。FuncInterfaceDemo.javapackage org.lambda;import java.util.function.*;/ 导入包含预定义接口的包public class FuncInterfaceDemo public static void main(String args) int n = Integer.parseInt(args0);IntPredicate isEven = (value)-(value % 2) = 0; / lambda表达式实现预定义接口if(isEven.test(n)System.out.println(n + 是偶数);elseSystem.out.println(n + 是奇数);6.3.3 Lambda6.3.3 Lambda表达式与匿名内部类表达式与匿名内部类lambda表达式是匿名内部类(见3.5.2节)的一种简化,因此它可以部分取代匿名内部类的作用,两者存在如下相同点:llambda表达式与匿名内部类一样,都可以直接访问final局部变量,以及外部类的成员变量(包括实例变量和类变量)。llambda表达式创建的对象与匿名内部类生成的对象一样,都可

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论