OOP-Java-13

注解、反射、内部类、匿名内部类与Lambda表达式

  1. 类关系:
    1. 组合
    2. 继承(is a)(子类属于父类)
    3. 内部类(用于当前所在类的内部,局部类)
      1. 类的内部类(类内方法外)
      2. 方法内的类,就叫内部类
    4. 匿名内部类:如果内部类只用一次,可以定义为匿名内部类
      1. 直接创建匿名内部类 A a = (new A(){ }); //定义一个A的子类,可以写类体
      2. 作为一个对象参数,传入需要该参数的方法。
    5. lambda表达式(实现的是函数式接口,就可以把匿名内部类转换成lambda表达式)
      1. (类型 1, 类型 2)->{ } (见课本p264)

注解

  1. 注解也叫元数据,就是用来描述数据的数据。它其实就是程序代码里的特殊标记,这些标记可以在编译、类加载、运行时被读取并执行相应的处理。注解主要用于告知编译器要做什么事情;
  2. 在程序中可对任何程序元素进行注解;
  3. 注解在不改变程序逻辑的情况下在源文件中嵌入一些补充信息;
  4. 注解的格式是@注解名,根据注解的作用分为基本注解元注解(或称元数据注解)自定义注解三种,都实现了java.lang.annotation.Annotation接口
  5. 基本注解(包括5种)
    @Deprecated
    @Override
    @SuppressWarnings
    @SafeVarargs
    @FunctionalInterfase
  6. 元注解(包括6种)
    @Target
    @Retention
    @Document
    @Inherited
    @Repeatable
    类型注解
    7.自定义注解(自定义一个注解,其格式如下:)
    [public] @interface 注解名{
    数据类型 成员变量名() [default 初始值];
    }
    

反射机制(动态绑定)

  1. Java的反射(Reflection)机制是指在程序的运行状态中,可以动态获取程序信息以及动态调用对象的功能。
  2. Class类是一个比较特殊的类,它是反射机制的基础,Class类的对象表示正在运行的Java程序中的类或接口,也就是任何一个类被加载时,即将类的class的文件(字节码文件)读入内存的同时,都自动为之创建一个Class对象
  3. 教材中表13.4列出了Class类的一些常用的方法
  4. 获得Class对象有如下三种方式:
    1. 使用Class类的静态方法forName(String className)
    2. 用类名调用该类的class属性来获得该类对应的Class对象
    3. 用对象调用getClass()方法来获得该类对应的Class对象
  5. 反射机制中除了上面介绍的Class类之外,还需要java.lang.reflet包中的Constructor类、Method类、Field类和Parameter类。
  6. 教材中表13.5至13.9给出了这些类的常用方法
  7. 见教材【例13.2】

内部类与匿名内部类

内部类
  1. 内部类(成员类):定义在类中的类,可以看成是外部类的一个成员。主要作用是将逻辑上相关的类放到一起。
  2. 内部类也可以拥有自己的成员变量与成员方法。
  3. 源文件编译后,内部类产生一个名为外部类$内部类的字节码文件。
  4. 内部类不能与包含它的外部类名相同。
  5. 见教材【例13.3】

  6. 内部类的特性:
    内部类前面用final修饰,则表明该内部类不能被继承;
    内部类可以定义为abstract,但需要被其他的内部类继承或实现;
    内部类可以是一个接口,该接口必须由另一个内部类实现;
    内部类不但可以在类里定义,也可以在程序块之内定义。
    内部类如果被声明为static,则静态内部类将自动转化为“顶层类”,而且不能引用外部类成员或其他内部类中的成员。非静态内部类不能声明静态成员,只有静态内部类才能声明静态成员。
    在内部类中可直接引用外部类的所有成员;
    在外部类中,通过创建内部类的对象引用内部类中的成员;
    在封装内部类的外部类之外访问内部类时,内部类须为public,必须在内部类名前冠以其所属外部类的名字才能使用;在用new创建内部类时,也需在new前冠以外部类的对象变量。
匿名内部类
  1. 定义类的目的是利用该类创建对象,如果某个类的对象只使用一次,则可以在定义类的同时创建该类的一个对象,以这种方式定义的类不用取名字,所以称为匿名内部类。
  2. 定义匿名内部类时直接用其父类或父接口名字:
    new TypeName(){
          类体
    }
    
  3. TypeName表示匿名内部类的父类或父接口
  4. 匿名内部类返回一个对象的引用,可以直接使用或将其赋给一个引用变量:
    TypeName obj = new TypeName(){类体};
  5. 也可以将匿名内部类对象作为方法调用的参数:
    someMethod(new TypeName() {类体});
  6. 创建匿名内部类可以有效地简化代码,也可用来弥补内部类里没有定义到的方法。
  7. 见教材【例13.4】 【例13.5s】

函数式接口与Lambda表达式

函数式接口
  1. 是指只包含一个抽象方法的接口,因此也称为单抽象方法接口。
  2. 每一个Lambda表达式是函数式接口编程的简化形式,可以将Lambda表达式看作是实现函数式接口的匿名内部类的一个对象。
  3. 为了让编译器能确保一个接口满足函数式接口的要求,Java提供了@FunctionalInterface注解。
lambda表达式
  1. Lambda表达式是一种匿名方法,使用它会创建一个与匿名内部类等价的对象,可以看作是使用精简语法的匿名内部类。
  2. Lambda表达式通常由参数列表、箭头和方法体三部分组成,其语法格式如下:
    (类型1 参数1,类型2 参数2,……)->{方法体}
  3. 见教材例13.6~13.8

Lambda表达式作为方法的参数
  1. Lambda表达式可以作为参数传递给方法,将可执行代码作为参数传递给方法
  2. 为了将Lambda表达式作为参数传递,接受Lambda表达式的参数必须是与该Lambda表达式兼容的函数式接口类型。
  3. 见教材例13.9

方法引用

  1. 方法引用可以理解为是Lambda表达式的另外一种表现形式,方法引用就是用双冒号运算符来“::”简化Lambda表达式的。
  2. 对于方法引用,Java定义了如下4种引用方式:
    对象名::实例方法名
    类名::静态方法名
    类名::实例方法名
    类名::new
  3. 见教材例13.10~13.11


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达,可以邮件至 963614756@qq.com。