《Java核心技术》笔记——第六章

文章目录

  • CH6.接口、lambda表达式与内部类
    • 1.接口基本
    • 2.常用接口
    • 3.lambda表达式
    • 4.内部类
    • 5.服务加载器与代理

前章: 第三章~第五章的学习笔记

CH6.接口、lambda表达式与内部类

1.接口基本

  1. 接口基本——interface声明,方法无需指明public(默认都是public),继承时使用implements关键字,接口支持多继承。接口可以看做一个c++中纯虚的抽象基类,它代表的含义是:继承自这个接口的类应该具有某些行为(接口的函数),而不在乎具体这些行为怎么实现的
  2. 接口中不能包含实例字段,但是可以包含常量(字段也都是默认public)
  3. 接口可以继承接口
  4. 接口中同样可以定义静态方法、私有方法(不知道为什么这么做)
  5. 接口的方法可以有默认实现,需要有关键字default——可以用于接口演化,比如接口新增一个方法,原来实现这个接口的类就编不过了,如果新增的方法加default给一个默认的实现,则原来的代码可以编过(会使用这个新方法的默认实现)
  6. 同名函数冲突——类与接口中有同名函数,同时继承自该类与该接口的类会“优先类”;接口与接口有同名函数,看继承者实现谁,如果两个接口有一个有默认实现,继承者必须定义同名函数,可以通过接口名.super.同名方法指定调谁的实现=>因为类优先,super含义就是父类(因为单继承,父类只可能有一个),而父接口应该用接口名.super代表
  7. 一种特殊的接口,标记接口,没有任何方法的接口,只是作为标记作用,使其子类可以使用instanceof判定是否有该标记,如cloneable就是标记接口——每个类继承自Object,都有Object.clone方法,但是这个方法是protected的,无法使用,需要在子类中声明为public,并调用super.clone的实现;但是这样会抛出CloneNotSupportedException,这是因为Object.clone的实现中判断了this instanceof Cloneable,不是的话会抛出异常
  8. 匿名接口——可以直接new一个接口,然后在{}中写实现,这个接口实现类是匿名的,无法再生成该类的一个实例

2.常用接口

  1. Comparable或者Comparable——Array的比较要求比较的元素有实现该接口(这也是函数式接口)
  2. Cloneable——可克隆的接口
  3. Predicate——专门用来接受判断lambda表达式的函数式接口
  4. Supplier——供应者接口(函数式接口,有一个T get()函数),用于懒加载,如Object.requireNonNullElseGet(T,Supplier)可以在传入T类型的参数为null时利用Supplier生成一个默认的实例(为null的情况可能比较少,所以传入一个将来要调的方法而不是传入一个实例,以实现懒计算
  5. Comparator接口——用于比较,其中的一些静态/成员方法用于生成Comparator,如comparing,thenComparing,naturalOrdr,reverOrder,reversed等;额外的一个小点,Comparator中有两个抽象函数但是依然是函数式接口,这是因为,其中一个是从Object继承来的重写的equals函数(接口也继承自Object类)

3.lambda表达式

  1. lambda表达式基本:(参数列表)->{函数体}——当参数列表类型可以由接收的函数式接口推断出的话,可以省略类型;在此基础上如果还只有一个参数,括号也可以省略;如果函数体只有一个语句,可以省略{}

  2. 与函数式接口的兼容:lambda表达式可以赋值给一个函数式接口(什么叫函数式接口——只有一个抽象函数的接口),与函数式接口完全兼容大大拓展了lambda表达式的适用范围
    《Java核心技术》笔记——第六章_第1张图片
    《Java核心技术》笔记——第六章_第2张图片

  3. 方法引用,等价于对应形式的lambda表达式,也可以用函数式接口对象接收,三种形式:

    • object::instanceMethod==>(参数列表)->object.instanceMethod(参数列表);唯一不同的是方法引用会马上检测object是否为null,而对应的lambda表达式会等到调用时才检测object是否为null
    • Class::instanceMethod==>(Class类参数 self,参数列表)->self.instanceMethod(参数列表);
    • Class::staticMethod==>(参数列表)->Class.staticMethod(参数列表);
  4. 构造器引用——与方法引用一样,只不过方法名为new,如object::new,以及数组形式的构造器object[]::new;调用的构造器重载版本根据具体场景推断

  5. @FunctionalInterface注解可以表明这个接口是函数式接口,在向该接口增加抽象方法时会报错,且javadoc中会标明这个接口是函数式接口

  6. lambda表达式的捕获——无需像c++一样写捕获列表,直接捕获lambda表达式所在作用于变量即可(值传递),称为自由变量,同时无法捕捉会变的变量

4.内部类

  1. 内部类——与c++的内部类一样,不过不同的是,
    • java内部类初始化的时候会默认传入外部类的this指针,使其可以访问创建它的外部类对象
    • java内部类在外部类外面创建的话得加外部类的对象,比如outClassObj.new InnerClass(),而不能直接new OutClass.InnerClass
  2. 局部内部类——在函数内定义的类;除了像一般内部类一样访问外部类的数据,还可以访问函数的局部变量(像lambda表达式一样捕获,只能捕获事实不变量)
  3. 匿名内部类——如匿名接口,实际也可以定义继承自普通(非接口)类的匿名子类;匿名内部类没有构造函数,可以通过初始化块来初始化数据–>引申一个双括号初始化技巧
  4. 静态内部类——加static标识
class OuterClass{
    public static class InnerClass{
        ...
    }
}
  • 静态内部类才与c++中的内部类相当;静态内部类不像一般内部类,创建的时候不会传入外部类的对象指针;静态内部类也成为嵌套类
  • 构造时可以直接new OuterClass.InnerClass()构造
  • 与常规内部类不同,静态内部类可以有静态字段和方法
  • 接口内部声明的内部类自动是static和public

5.服务加载器与代理

略。看不懂,以后有机会再拜读

你可能感兴趣的:(java,c++,开发语言)