Java程序设计基础 课件 第8章 内嵌类与lambda表达式_第1页
Java程序设计基础 课件 第8章 内嵌类与lambda表达式_第2页
Java程序设计基础 课件 第8章 内嵌类与lambda表达式_第3页
Java程序设计基础 课件 第8章 内嵌类与lambda表达式_第4页
Java程序设计基础 课件 第8章 内嵌类与lambda表达式_第5页
已阅读5页,还剩53页未读 继续免费阅读

下载本文档

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

文档简介

第8章内嵌类与lambda表达式1教学目标(1) 理解内嵌类概念(2) 掌握成员内部类的定义和使用(3) 掌握局部内部类的定义和使用(4) 掌握匿名内部类的定义和使用(5) 掌握静态内嵌类的定义和使用(6) 掌握lambda表达式的语法,理解并能定义函数式接口(7) 理解lambda表达式的作用域,掌握lambda表达式如何访问外部变量(8) 掌握lambda表达式静态方法引用、实例方法引用、构造方法引用(9) 掌握ArrayList的方法forEach()、removeIf()与lambda表达式的联合使用(10)掌握Comparator接口的使用2内容38.1内嵌类8.1.1成员内部类8.1.2局部内部类8.1.3匿名内部类8.2.2

lambda表达式作用域8.2.3方法引用8.2.4lambda表达式与ArrayList8.1.4静态内嵌类8.2lambda表达式8.2.1lambda表达式语法8.2.5Comparator接口内容48.1内嵌类8.1.1成员内部类8.1.2局部内部类8.1.3匿名内部类8.2.2

lambda表达式作用域8.2.3方法引用8.2.4lambda表达式与ArrayList8.1.4静态内嵌类8.2lambda表达式8.2.1lambda表达式语法8.2.5Comparator接口8.1内嵌类内嵌类(nestedclass),是指定义在另一个类中的类。包含内嵌类的外部类被称为内部类的外嵌类。使用内嵌类的主要原因:内嵌类可以对同一包中的其它类隐藏,增强了代码的封装性,使得代码更加模块化和可维护。内嵌类可以直接访问外嵌类的成员变量和方法,复用外嵌类的代码,无需通过复杂的接口实现或继承关系来实现代码复用。58.1内嵌类内嵌类包括静态内嵌类:显式使用static修饰的内嵌类隐式静态类:成员枚举类、局部枚举类、成员记录类、局部记录类、一个接口的成员类内部类:非显式、隐式静态的内嵌类实名内部类匿名内部类678-1内嵌类可以分为

[填空1]

[填空2]

。作答填空题1分88-2关于内嵌类的描述错误的是()内嵌类可以对同一包的其他类隐藏内嵌类可以增强代码的封装性内嵌类不能实现代码复用内嵌类可访问外嵌类的数据域和方法ABCD提交单选题1分内容98.1内嵌类8.1.1成员内部类8.1.2局部内部类8.1.3匿名内部类8.2.2

lambda表达式作用域8.2.3方法引用8.2.4lambda表达式与ArrayList8.1.4静态内嵌类8.2lambda表达式8.2.1lambda表达式语法8.2.5Comparator接口内容108.1内嵌类8.1.1成员内部类8.1.2局部内部类8.1.3匿名内部类8.2.2

lambda表达式作用域8.2.3方法引用8.2.4lambda表达式与ArrayList8.1.4静态内嵌类8.2lambda表达式8.2.1lambda表达式语法8.2.5Comparator接口8.1.1成员内部类成员内部类是最普通的内部类,它的定义为位于另一个类的内部。Java语言定义成员内部类一般形式如下:修饰符1可以使用public或缺省(无修饰符)修饰符2可以是public、protected、private或缺省当内部类被private修饰时,该内部类在外嵌类的外部不可见当内部类被public修饰时,该内部类在外嵌类的外部可见成员内部类也可以继承父类、实现接口11[修饰符1]classOuterClass{//外嵌类//...[修饰符2]classNestedClass[extends…][implements…]{//成员内部类//...}}8.1.1成员内部类外嵌类和实名内部类都会产生自己独立的字节码文件。对于实名内部类,其字节码文件的文件名为:外嵌类名$实名内部类名.class。简单示例:程序清单8-1CircleNestDemo.java程序清单8-1对应的Java源文件只有一个:CircleNestDemo.java,产生的字节码文件有两个:CircleNestDemo.class,CircleNestDemo$Draw.class。128.1.1成员内部类需要注意的是,当成员内部类拥有和外嵌类同名的成员变量或者方法时,会发生隐藏现象。这时,在成员内部类中,默认访问的是成员内部类的成员。如果要在成员内部类中访问外嵌类的同名成员,需要以下面的形式进行访问:外嵌类名.this.成员变量外嵌类名.this.成员方法创建成员内部类实例的一般语法形式如下:外嵌类类名.内部类类名内部类对象名=外嵌类实例名.new内部类类名(参数列表);成员内部类允许定义静态方法,在外嵌类的外部被引用时,需使用“外嵌类名.内部类名.静态方法”进行调用。程序清单8-2展示了成员内部类实例的创建、成员内部类静态方法的定义及其调用、同名成员的隐藏现象:InnerClassDemo1.java138.1.1成员内部类虽然成员内部类可以访问外嵌类的所有成员,但是,反过来,外嵌类却不能直接访问成员内部类的成员。如果要在外嵌类中访问成员内部类的成员,必须先创建一个成员内部类的对象,再通过这个对象的引用来访问成员内部类的成员。示例:程序清单8-3CircleNestDemo2.java14158-3如果要在成员内部类中访问外嵌类的同名成员方法,需要以下面的形式进行访问:

[填空1]

作答填空题1分168-4成员内部类允许定义静态方法,在外嵌类的外部被引用时,需使用“

[填空1]

”进行调用。作答填空题1分内容178.1内嵌类8.1.1成员内部类8.1.2局部内部类8.1.3匿名内部类8.2.2

lambda表达式作用域8.2.3方法引用8.2.4lambda表达式与ArrayList8.1.4静态内嵌类8.2lambda表达式8.2.1lambda表达式语法8.2.5Comparator接口8.1.2局部内部类局部内部类是指定义在外嵌类的方法里面或者一个语句块作用域里面的类访问权限仅限于方法内或者该语句块作用域内与方法的局部变量一样,不能用public、protected、private以及static、sealed修饰符修饰。对外部世界是完全隐藏的,体现了更好的封装性。不仅能访问外嵌类成员,还能访问所在方法或所在语句块作用域内的局部变量。示例:程序清单8-4LocalInnerClassDemo.java18198-5局部内部类是指定义在外嵌类的

[填空1]

里面或者一个

[填空2]

作用域里面的类。作答填空题2分内容208.1内嵌类8.1.1成员内部类8.1.2局部内部类8.1.3匿名内部类8.2.2

lambda表达式作用域8.2.3方法引用8.2.4lambda表达式与ArrayList8.1.4静态内嵌类8.2lambda表达式8.2.1lambda表达式语法8.2.5Comparator接口8.1.3匿名内部类在使用局部内部类的场景中,如果局部内部类的名称只被使用一次,仅用于创建这个局部内部类的对象,那么可以对局部内部类进行简化,可以无需指定局部内部类的类名。这样的一个没有名字的局部内部类被称为匿名内部类。示例:程序清单8-5AnnonymousInnerClassDemo.java218.1.3匿名内部类通常,匿名内部类的语法形式如下:new父类型名称(父类型构造方法参数列表){

匿名内部类的成员方法和成员数据域定义;}这里的父类型既可以是接口,也可以是一个类(通常是抽象类)。当父类型是接口时,父类型构造方法参数列表为空,调用的构造方法是Object(),语法形式可以简化为:new接口名(){

数据域定义; 方法定义;}228.1.3匿名内部类匿名内部类还具有以下几个特点:一个匿名内部类没有类名,而构造方法的名称必须与类名相同,因此,匿名内部类没有构造方法定义。一个匿名内部类必须实现父类型的所有抽象方法,因为匿名内部类自身不能是抽象的。每个匿名内部类都有自己对应的字节码文件,字节码文件命名形式是:外嵌类类名$n.class,在美元符号$后的符号n表示从1开始编号的整数。如果一个外嵌类有多个匿名内部类,那么这些匿名内部类的文件名从数字1开始编号命名,即:外嵌类类名$1.class、外嵌类类名$2.class、外嵌类类名$3.class、…。23248-5每个匿名内部类都有自己对应的字节码文件,字节码文件命名形式是:

[填空1]

作答填空题1分258-6下面关于匿名内部类的说法正确的是()匿名内部类必须提供一个无参构造方法匿名内部类只能继承一个类,不能实现接口匿名内部类可以实现接口,但必须提供构造方法匿名内部类必须实现父类型的所有抽象方法ABCD提交单选题1分内容268.1内嵌类8.1.1成员内部类8.1.2局部内部类8.1.3匿名内部类8.2.2

lambda表达式作用域8.2.3方法引用8.2.4lambda表达式与ArrayList8.1.4静态内嵌类8.2lambda表达式8.2.1lambda表达式语法8.2.5Comparator接口8.1.4静态内嵌类用关键字static显式修饰的内嵌类是静态内嵌类,静态内嵌类没有对外嵌类对象的引用。显式声明静态内嵌类的一般形式如下所示:[修饰符1]classOuterClass{//外嵌类

//...[修饰符2]staticclassNestedClass{//静态内嵌类

//...}}修饰符1可以使用public或缺省(无修饰符)修饰符2可以是public、protected、privated或缺省隐式声明的静态内嵌类包括:成员枚举类、局部枚举类、成员记录类、局部记录类、一个接口的成员类278.1.4静态内嵌类静态内嵌类与成员内部类不同,不再持有外嵌类的引用,即不能使用“外嵌类名.this”引用外嵌类的实例成员。静态内嵌类对象的创建语法形式如下:外嵌类名.静态内嵌类内部类对象名=new外嵌类名.静态内嵌类();程序清单8-6StaticNestedClsDemo.Java28298-7隐式声明的静态内嵌类包括()成员枚举类局部内部类局部记录类匿名静态内部类ABCD提交多选题1分内容308.1内嵌类8.1.1成员内部类8.1.2局部内部类8.1.3匿名内部类8.2.2

lambda表达式作用域8.2.3方法引用8.2.4lambda表达式与ArrayList8.1.4静态内嵌类8.2lambda表达式8.2.1lambda表达式语法8.2.5Comparator接口8.2.1lambda表达式语法lambda表达式是JAVASE8提供的一种新特性,可以看做是一段可以传递的代码。在Java语言中,lambda表达式还可以被称为闭包或匿名函数。下面用lambda表达式改写程序清单8-5的示例,说明lambda表达式如何替代匿名内部类,如程序清单8-7所示。程序演示:LambdaDemo1.java函数式接口是一个不能使用关键字seal修饰、必须有且只有一个抽象方法(除了Object的public方法)的接口。函数式接口可以使用注解@FunctionalInterface进行修饰,其作用仅仅在于强迫Java编译器对接口进行语法检查,是否只定义了一个抽象方法,如果否,Java编译器就会报错。不使用注解@FunctionalInterface,也能正确运行。函数式接口也可以被成为单抽象方法(SingleAbstractMethod,SAM)接口。31328-8函数式接口可以使用注解

[填空1]

进行修饰。作答填空题1分8.2.1lambda表达式语法lambda表达式可以简化函数式接口的实现338.2.1lambda表达式语法lambda表达式由三个部分组成:参数列表、箭头、方法体,一般语法形式如下:(数据类型参数名称)->{语句组}类型推断:程序清单8-7第8行必须先指定apple对象的类型是EatMethod,这样Java编译器就可以推断出赋值语句右边的表达式返回的是一个实现了函数式接口EatMethod的匿名类对象。lambda表达式的参数列表既可以和函数式接口中抽象方法的参数列表完全一致,也可以省略参数列表中的数据类型,此时参数的数据类型由编译器隐式推断。当参数列表只有一个参数时,圆括号可以省略。当参数列表为空时,必须要使用一对圆括号。34358-9lambda表达式由三个部分组成:

[填空1]

[填空2]

、方法体作答填空题2分8.2.1lambda表达式语法lambda表达式的方法体如果只有一条语句,那么方法体部分的花括号可以省略。并且,如果这一条语句是return语句,可以省略关键字return。因此,程序清单8-7第8行可以进一步简化为:EatMethodapple=()->eatInfo+":榨苹果汁";程序清单8-7第8行-9行,可以简化为如下一条语句:System.out.println(info(()->eatInfo+":榨苹果汁"));此时,lambda表达式直接替换了方法的参数,而且分号;是不需要的。由于方法info的形参类型确定为接口类型EatMethod,所以Java编译器会推断出这个lambda表达式是返回一个实现了函数式接口EatMethod的匿名类对象。368.2.1lambda表达式语法lambda表达式能用于简化函数式接口的实现,对于函数式接口的定义需要准确理解。函数式接口不仅要有一个抽象方法,而且该抽象方法不能是类Object的public方法37例,下面接口定义不是一个函数式接口:interfaceNonFunc{booleanequals(Objectobj);}因为方法equals()是类Object的public方法。接口NonFunc的子接口可以是函数式接口,只要这个子接口声明了一个不是类Object成员的抽象方法,例如:interfaceFuncextendsNonFunc{intcompare(Stringo1,Stringo2);}8.2.1lambda表达式语法lambda表达式能用于简化函数式接口的实现,对于函数式接口的定义需要准确理解。函数式接口不仅要有一个抽象方法,而且该抽象方法不能是类Object的public方法38Java语言提供的有用接口java.util.Comparator<T>是一个函数式接口,定义如下:interfaceComparator<T>{booleanequals(Objectobj);//类Object的public方法intcompare(To1,To2);//不是类Object的public方法}接口Func是否函数式接口呢?interfaceFunc{intm();Objectclone();}接口Func不是函数式接口8.2.1lambda表达式语法展示lambda表达式带有1个、2个参数的情况:程序清单8-8LambdaDemo2.javalambda表达式的省略规则如下:(1)lambda表达式参数列表中参数的数据类型可以省略,而且必须同时省略,不允许省略其中一部分参数的数据类型,而另一部分参数不省略。(2)在lambda表达式省略参数的数据类型之后,如果参数列表只有一个参数时,圆括号可以省略。其他情况下,圆括号不能省略。具体地,当参数列表为空时,不能省略圆括号;当参数列表中的参数个数不少于2个时,也不能省略圆括号。(3)当lambda表达式方法体中的语句只有一条时,可以省略花括号和分号。进一步,当这一条语句是return语句时,return也必须省略。39408-10当lambda表达式方法体中的语句只有一条时,可以省略

[填空1]

[填空2]

作答填空题2分8.2.1lambda表达式语法Java编译器在解析一个lambda表达式时,等同于是从一个匿名内部类创建一个匿名对象。通常,Java编译器处理lambda表达式有三个步骤:①确定lambda表达式的数据类型;②确定参数的数据类型;③确定方法体语句。41428-11下列选项中符合lambda表达式语法的是()x->returnx+1x,y->x+yx->{x=x*2;x+1;} x->{x=x*2;returnx+1;}ABCD提交单选题1分内容438.1内嵌类8.1.1成员内部类8.1.2局部内部类8.1.3匿名内部类8.2.2

lambda表达式作用域8.2.3方法引用8.2.4lambda表达式与ArrayList8.1.4静态内嵌类8.2lambda表达式8.2.1lambda表达式语法8.2.5Comparator接口8.2.2lambda表达式作用域lambda表达式的体与其形成的嵌套块具有相同的作用域。因此,在lambda表达式中声明一个与其外部作用域同名的局部变量是不合法的。lambda表达式访问外围方法或类中的变量,有一个重要的限制:只能引用外部变量的值而不能改变外部变量的值。并且,如果在lambda表达式中引用了一个外部变量,这个外部变量也不能在外部改变。lambda表达式访问外围作用域的变量必须是最终变量(即常量)或事实最终(effectivefinal)变量。事实最终变量是指一个变量被初始化后就不再为其赋新值。44458-12lambda表达式访问外围作用域的变量必须是常量或

[填空1]

变量。(只填中文)作答填空题1分内容468.1内嵌类8.1.1成员内部类8.1.2局部内部类8.1.3匿名内部类8.2.2

lambda表达式作用域8.2.3方法引用8.2.4lambda表达式与ArrayList8.1.4静态内嵌类8.2lambda表达式8.2.1lambda表达式语法8.2.5Comparator接口8.2.3方法引用方法引用也称为函数引用,是指在lambda表达式中引用一个已经存在的方法,使其替代lambda表达式完成接口的实现。根据方法类型,可以分为:静态方法引用、实例方法引用、构造方法引用。静态方法引用静态方法引用的一般语法形式:类名::静态方法名程序清单8-10给出了一个静态方法引用的示例:ReferStaticMethod.java(1)静态方法引用,只需要静态方法名,不需要在方法名后加圆括号。(2)被引用的静态方法的参数列表和返回值,与lambda表达式实现的接口中抽象方法的参数列表和返回值一致。被引用的静态方法的方法体,与lambda表达式的方法体一致。478.2.3方法引用实例方法引用实例方法引用的一般语法形式:对象名::实例方法名示例:程序清单8-11ReferInstanceMethod.java(1)实例方法引用与静态方法不同,需要使用对象名,对象名可以是匿名的。(2)实例方法引用,只需要实例方法名,不需要在方法名后加圆括号。(3)被引用的实例方法的参数列表和返回值,与lambda表达式实现的接口中抽象方法的参数列表和返回值一致。被引用的实例方法的方法体,与lambda表达式的方法体一致488.2.3方法引用构造方法引用构造方法引用的一般语法形式:类名::new示例:程序清单8-12ReferConstructor.java49508-13根据方法引用的方法类型,可以分为

[填空1]

引用、

[填空2]

引用、

[填空3]

引用。作答填空题1.5分内容518.1内嵌类8.1.1成员内部类8.1.2局部内部类8.1.3匿名内部类8.2.2

lambda表达式作用域8.2.3方法引用8.2.4lambda表达式与ArrayList8.1.4静态内嵌类8.2lambda表达式8.2.1lambda表达式语法8.2.5Comparator接口8.2.4lambda表达式与ArrayListArrayList中有两个方法可以使用lambda表达式,这两个方法是:forEach()、removeIf。(1)publicvoidforEach(Consumer<?superE>action)该方法可对当前列表的每个元素执行给定的操作,直到处理完所有元素或该操作引发异常为止。如果指定了迭代顺序,则操作将按迭代顺序执行。操作引发的异常会中继到调用方。(2)publicbooleanremoveIf(Predicate<?superE>filter)该方法删除当前列表中满足给定谓词(即某种条件)的所有元素。迭代期间或谓词引发的错误或运行时异常会中继到调用方。示例:程序清单8-13ListWithLambda.java528.2.4lambda表达式与ArrayList补充:Consumer接口是一个函数式接口,它定义了一个接受单个参数并且不返回结果的操作。Consumer接口包含一个抽象方法voidaccept(Tt),该方法接受一个参数,表示要执行的操作。Consumer接口通常用于表示一些需要对输入进行处理但不产生返回值的操作。它可以被用于各种场景,例如集合操作、事件处理等。Predicate接口是一个函数式接口,用于表示一个断言(predicate),即接受一个参数并返回一个布尔值的操作。它定义了一个名为test的抽象方法,该方法接受一个参数并返回一个布尔值,用于表示对给定输入的条件判断。Predicate接口通常用于在函数式编程中进行条件过滤或测试。它提供了一种方便的方式来定义和组合条件,以便对集合元素、对象或任何其他类型的数据进行过滤或测试。53548-14成绩列表对象scoreList存储了一个班的Java课程成绩,请使用removeIf方法筛选出不及格的成绩:

[填空

温馨提示

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

评论

0/150

提交评论