接口、lambda表达式与内部类

  • 接口:用来描述类应该做社么,而不指定它们具体应该如何做
  • lambda表达式:一种很简洁的方法,用来创建可以在将来某个时间点执行的代码块
  • 内部类:定义在另外一个类的内部,它们的方法可以访问包含它们的外部类的字段。内部类技术在设计具有相互协作关系的类集合时很有用。
  • 代理:实现任意接口的对象

接口

接口的概念

接口不是类,而是对希望符合这个接口的类的一组需求(定义规范)

  • 接口中的所有方法都自动时public方法,在接口中声明方法时,不需要提供关键字public。
  • 接口中的字段总是 public static final
  • 提供实例字段和方法实现的任务应该由实现接口的那个类来完成。
  • 在实现接口时,必须把方法声明为public。
  • Comparable接口的文档建议CompareTo方法应当与equals方法兼容。

接口的属性

  • 接口不是类,不能new运算符实例化接口,即不能构造接口对象
 x=new Comparable(...);//ERROR,不能构造接口对象
  • 可以声明接口变量
 Comparable x;//可以声明接口变量
  • 接口变量必须引用实现了这个接口的类对象
 Comparable x;//可以声明接口变量 
x= new 实现了Comparable接口的类(...)//实现Comparable接口类的构造器
  • 可以使用、将想要实现的各个接口分隔开。

接口与abstract类

  • 使用abstract类标识通用属性存在一个严重的问题,每个类只能扩展一个类。
    java不支持多重继承,主要原因为多重继承让语言变得非常复杂(如同C++的虚基类,控制规则和横向指针类型转换),或效率会降低(如同Eiffel)
  • 接口可以提供多重继承的大多数好处,同时还能避免多重继承的复杂性和低效性。

静态和私有方法

  • jdk 8中允许在接口中增加静态方法。

默认(default)方法

  • 可以为接口方法提供一个默认实现,必须用default修饰符标记该方法。

解决默认方法冲突

  • 千万不要让一个人default方法重新定义Object类中的某个方法。由于“类优先”规则,这样的方法绝对无法超越Object中的方法。

接口与回调

  • 回调:是一种常见的设计模式。在这种模式中,可以指定某个特定事件发生时应该采取的动作。

lambda表达式

为什么引用lambda表达式

  • lambda表达式是一个可传递的代码块,可以在以后执行一次或多次。
  • 在java中传递一个代码段并不容易,不能直接传递代码块。java是一种面向对象的语言,所以必须构造一个对象,这个对象的类需要有一个方法包含所需的方法。

lambda表达式的语法

(String first,String second)
   -> first.length() - second.length()

lambda表达式就是一个代码块,以及必须传入代码的变量规范。

  • 如果可以推导出lambda表达式的参数类型,可以忽略其类型。
  • 如果方法只有一个参数,而且这个参数的类型可以推导得出,那么甚至可以忽略小括号。

函数式接口

  • 只有一个抽象方法的接口,需要这种接口的对象时,就可以提供一个lambda表达式。这种接口称为函数式接口

方法引用

lambda表达式涉及一个方法。

var timer = new Timer(1000, event -> System.out.println(event));
//表达式System.out::println是一个方法引用,表示编译器生成一个函数式接口的实例,覆盖这个接口的抽象方法来调用给定的方法。
var timer = new Timer(1000, System.out::println);
  • object::instanceMethod
  • Class::instanceMethod
  • Class::staticMethod

构造器引用

  • 构造器引用与构造方法类似只不过方法名为new。例如Person::new是Person构造器的一个引用
Person[] people=stream.toArray(Person[]::new);

变量作用域

  • 在lambda表达式中,只能引用值不值不会改变的变量。
  • 在lambda表达式中引用一个变量,而这个变量可能在外部改变是不合法的。
  • lambda表达式中捕获的变量必须实际上是事实最终变量(这个变量初始化后就不会再为它赋新值)。

处理lambda表达式

使用lambda表达式的重点是延迟执行,如果想要立即执行代码,完全可以直接执行,而无须把它包装在一个lambda表达式中。
延迟执行的原因:

  • 在一个单独的线程中运行代码
  • 多次运行代码
  • 在算法的适当位置运行代码(排序中的比较操作)
  • 在发生某种情况时执行代码(点击了一个按钮,数据到达等)
  • 只在必要时才运行代码

内部类

内部类是定义在另一个类中的类。
使用内部类的原因:

  • 内部类可以对同一个包中的其他类隐藏
  • 内部类方法可以访问定义这个类的作用域中的数据,包括原本私有的数据

//TODO

代理

//TODO


这个家伙很懒,啥也没有留下😋