注解、反射、内部类、匿名内部类与Lambda表达式
- 类关系:
- 组合
- 继承(is a)(子类属于父类)
- 内部类(用于当前所在类的内部,局部类)
- 类的内部类(类内方法外)
- 方法内的类,就叫内部类
- 匿名内部类:如果内部类只用一次,可以定义为匿名内部类
- 直接创建匿名内部类 A a = (new A(){ }); //定义一个A的子类,可以写类体
- 作为一个对象参数,传入需要该参数的方法。
- lambda表达式(实现的是函数式接口,就可以把匿名内部类转换成lambda表达式)
- (类型 1, 类型 2)->{ } (见课本p264)
注解
- 注解也叫元数据,就是用来描述数据的数据。它其实就是程序代码里的特殊标记,这些标记可以在编译、类加载、运行时被读取并执行相应的处理。注解主要用于告知编译器要做什么事情;
- 在程序中可对任何程序元素进行注解;
- 注解在不改变程序逻辑的情况下在源文件中嵌入一些补充信息;
- 注解的格式是
@注解名
,根据注解的作用分为基本注解、元注解(或称元数据注解)与自定义注解三种,都实现了java.lang.annotation.Annotation接口 - 基本注解(包括5种)
@Deprecated
@Override
@SuppressWarnings
@SafeVarargs
@FunctionalInterfase - 元注解(包括6种)
@Target
@Retention
@Document
@Inherited
@Repeatable
类型注解
7.自定义注解(自定义一个注解,其格式如下:)[public] @interface 注解名{ 数据类型 成员变量名() [default 初始值]; }
反射机制(动态绑定)
- Java的反射(Reflection)机制是指在程序的运行状态中,可以动态获取程序信息以及动态调用对象的功能。
- Class类是一个比较特殊的类,它是反射机制的基础,Class类的对象表示正在运行的Java程序中的类或接口,也就是任何一个类被加载时,即将类的class的文件(字节码文件)读入内存的同时,都自动为之创建一个Class对象。
- 教材中表13.4列出了Class类的一些常用的方法
- 获得Class对象有如下三种方式:
- 使用Class类的静态方法
forName(String className)
- 用类名调用该类的
class
属性来获得该类对应的Class对象 - 用对象调用
getClass()
方法来获得该类对应的Class对象
- 使用Class类的静态方法
- 反射机制中除了上面介绍的Class类之外,还需要
java.lang.reflet
包中的Constructor
类、Method
类、Field
类和Parameter
类。 - 教材中表13.5至13.9给出了这些类的常用方法
- 见教材【例13.2】
内部类与匿名内部类
内部类
- 内部类(成员类):定义在类中的类,可以看成是外部类的一个成员。主要作用是将逻辑上相关的类放到一起。
- 内部类也可以拥有自己的成员变量与成员方法。
- 源文件编译后,内部类产生一个名为外部类$内部类的字节码文件。
- 内部类不能与包含它的外部类名相同。
见教材【例13.3】
- 内部类的特性:
内部类前面用final修饰,则表明该内部类不能被继承;
内部类可以定义为abstract,但需要被其他的内部类继承或实现;
内部类可以是一个接口,该接口必须由另一个内部类实现;
内部类不但可以在类里定义,也可以在程序块之内定义。
内部类如果被声明为static,则静态内部类将自动转化为“顶层类”,而且不能引用外部类成员或其他内部类中的成员。非静态内部类不能声明静态成员,只有静态内部类才能声明静态成员。
在内部类中可直接引用外部类的所有成员;
在外部类中,通过创建内部类的对象引用内部类中的成员;
在封装内部类的外部类之外访问内部类时,内部类须为public,必须在内部类名前冠以其所属外部类的名字才能使用;在用new创建内部类时,也需在new前冠以外部类的对象变量。
匿名内部类
- 定义类的目的是利用该类创建对象,如果某个类的对象只使用一次,则可以在定义类的同时创建该类的一个对象,以这种方式定义的类不用取名字,所以称为匿名内部类。
- 定义匿名内部类时直接用其父类或父接口名字:
new TypeName(){ 类体 }
- TypeName表示匿名内部类的父类或父接口
- 匿名内部类返回一个对象的引用,可以直接使用或将其赋给一个引用变量:
TypeName obj = new TypeName(){类体};
- 也可以将匿名内部类对象作为方法调用的参数:
someMethod(new TypeName() {类体});
- 创建匿名内部类可以有效地简化代码,也可用来弥补内部类里没有定义到的方法。
- 见教材【例13.4】 【例13.5s】
函数式接口与Lambda表达式
函数式接口
- 是指只包含一个抽象方法的接口,因此也称为单抽象方法接口。
- 每一个Lambda表达式是函数式接口编程的简化形式,可以将Lambda表达式看作是实现函数式接口的匿名内部类的一个对象。
- 为了让编译器能确保一个接口满足函数式接口的要求,Java提供了@FunctionalInterface注解。
lambda表达式
- Lambda表达式是一种匿名方法,使用它会创建一个与匿名内部类等价的对象,可以看作是使用精简语法的匿名内部类。
- Lambda表达式通常由参数列表、箭头和方法体三部分组成,其语法格式如下:
(类型1 参数1,类型2 参数2,……)->{方法体}
见教材例13.6~13.8
Lambda表达式作为方法的参数
- Lambda表达式可以作为参数传递给方法,将可执行代码作为参数传递给方法
- 为了将Lambda表达式作为参数传递,接受Lambda表达式的参数必须是与该Lambda表达式兼容的函数式接口类型。
见教材例13.9
方法引用
- 方法引用可以理解为是Lambda表达式的另外一种表现形式,方法引用就是用双冒号运算符来“::”简化Lambda表达式的。
- 对于方法引用,Java定义了如下4种引用方式:
对象名::实例方法名
类名::静态方法名
类名::实例方法名
类名::new 见教材例13.10~13.11
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达,可以邮件至 963614756@qq.com。