Java核心卷一之接口、lambda 表达式与内部类

首先 , 介绍一下接口 ( interface ) 技术 , 这种技术主要用来描述类具有什么功能,而并不 给出每个功能的具体实现。 一个类可以实现 ( implement )—个或多个接口,并在需要接口的地方, 随时使用实现了相应接口的对象 。 了解接口以后 , 再继续介绍而表达式,这是 一种表示可以在将来某个时间点执行的代码块的简洁方法。 使用 lambda 表达式 , 可以用一 种精巧而简洁的方式表示使用回调或变量行为的代码。 接下来, 讨论内部类 ( inner class ) 机制 。 理论上讲 , 内部类有些复杂 , 内部类定义在另 外一个类的内部, 其中的方法可以访问包含它们的外部类的域 。 内部类技术主要用于设计具 有相互协作关系的类集合。 在本章的最后还将介绍代理 ( proxy ) , 这是一种实现任意接口的对象 。 代理是一种非常 专业的构造工具 , 它可以用来构建系统级的工具 。

接口

接口概念

在 Java 程序设计语言中 , 接口不是类 , 而是对类的一组需求描述 , 这些类要遵从接口描 述的统一格式进行定义 。 接口中的所有方法自动地属于 public 。 因此 , 在接口中声明方法时 , 不必提供关键字 public 为了让类实现一个接口 , 通常需要下面两个步骤 : 1 ) 将类声明为实现给定的接口 。 2 ) 对接口中的所有方法进行定义 。 要将类声明为实现某个接口 , 需要使用关键字 implements : cl ass Employee implements Comparable  

接口的特性

接口不是类 , 尤其不能使用 new 运算符实例化一个接口 : x = new Comparable ( . . . ) ; / / ERROR 然而 , 尽管不能构造接口的对象 , 却能声明接口的变量 : Comparable x ; // OK 接口变量必须弓 I 用实现了接口的类对象 : x = new Employee ( . . . ) ; / / OK provided Employee implements Comparable 接下来 , 如同使用 instanceof 检查一个对象是否属于某个特定类一样 , 也可以使用 instance 检查一个对象是否实现了某个特定的接口 : if ( anObject instanceof Comparable ) { . . . } 与接口中的方法都自动地被设置为 public —样, 接口中的域将被自动设为 public static final 。 尽管每个类只能够拥有一个超类 , 但却可以实现多个接口 。这就为定义类的行为提供了 极大的灵活性 。 例如 , Java 程序设计语言有一个非常重要的内置接口 , 称为 Cloneable ( 将在 6.2 . 3 节中给予详细的讨论 。 ) 如果某个类实现了这个 Cloneable 接口 , Object 类中的 clone 方 法就可以创建类对象的一个拷贝 。 如果希望自己设计的类拥有克隆和比较的能力 , 只要实现 这两个接口就可以了 : 使用逗号将实现的各个接口分隔开 。 class Employee implements Cloneable , Comparable

接口与抽象类

为什么 Java 程序设计语言还要不辞辛苦地引入接口概念? 为什么不将 Comparable 直接设计成如下所示的抽象类。 然后 , Employee 类再直接扩展这个抽象类 , 并提供 compareTo 方法的实现 非常遗憾 , 使用抽象类表示通用属性存在这样一个问题 : 每个类只能扩展于一个类 。 假 设 Employee 类已经扩展于一个类 , 例如 Person , 它就不能再像下面这样扩展第二个类了 : class Employee extends Person , Comparable / / Error 但是可以实现多个接口 Java 的设计者选择了不支持多继承 , 其主要原因是多继承会让语言 本身变得非常复杂 ( 如同 C + + , ) 效率也会降低 ( 如同 Eiffel 。 ) 实际上, 接口可以提供多重继承的大多数好处 , 同时还能避免多重继承的复杂性和低效性 。

静态方法

在 Java SE 8 中 , 允许在接口中增加静态方法 。 理论上讲 , 没有任何理由认为这是不合法 的 。 只是这有违于将接口作为抽象规范的初衷。目前为止 , 通常的做法都是将静态方法放在伴随类中 。

lambda 表达式

lambda 表达式 , 这是这些年来 Java 语言最让人激动的一个变化 。 你会了解如何使用 lambda 表达式采用一种简洁的语法定义代码块 , 以及如何编写处理 lambda 表达式的代码

为什么引入 lambda 表达式

lambda 表达式是一个可传递的代码块 , 可以在以后执行一次或多次 。 到目前为止 , 在 Java 中传递一个代码段并不容易 , 不能直接传递代码段 _ Java 是一种面 向对象语言 , 所以必须构造一个对象 , 这个对象的类需要有一个方法能包含所需的代码 在其他语言中 , 可以直接处理代码块 。 Java 设计者很长时间以来一直拒绝增加这个特性 。 毕竟 , Java 的强大之处就在于其简单性和一致性 。 如果只要一个特性能够让代码稍简洁一些 , 就把这个特性增加到语言中 , 这个语言很快就会变得一团糟 , 无法管理 。 不过 , 在另外那些 语言中 , 并不只是创建线程或注册按钮点击事件处理器更容易 ; 它们的大部分 API 都更简单 、 更一致而且更强大 。 在 Java 中 , 也可以编写类似的 AP 丨利用类对象实现特定的功能 , 不过这 种 API 使用可能很不方便 。

lambda 表达式的语法

  • 一个 Lambda 表达式可以有零个或多个参数
  • 参数的类型既可以明确声明,也可以根据上下文来推断。例如:(int a)(a)效果相同
  • 所有参数需包含在圆括号内,参数之间用逗号相隔。例如:(a, b) 或 (int a, int b) 或 (String a, int b, float c)
  • 空圆括号代表参数集为空。例如:() -> 42
  • 当只有一个参数,且其类型可推导时,圆括号()可省略。例如:a -> return a*a
  • Lambda 表达式的主体可包含零条或多条语句
  • 如果 Lambda 表达式的主体只有一条语句,花括号{}可省略。匿名函数的返回类型与该主体表达式一致
  • 如果 Lambda 表达式的主体包含一条以上语句,则表达式必须包含在花括号{}中(形成代码块)。匿名函数的返回类型与代码块的返回类型一致,若没有返回则为空

函 数 式 接 口

对于只有一个抽象方法的接口 , 需要这种接口的对象时 , 就可以提供一个 lambda 表达 式 。 这种接口称为函数式接口 ( functional interface ) 。 为了展示如何转换为函数式接口 , 下面考虑 Arrays . sort 方法 。 它的第二个参数需要一个 Comparator 实例 , Comparator 就是只有一个方法的接口 , 所以可以提供一个 lambda 表达式 : Arrays . sort ( words , (first , second ) - > first . lengthO - second . lengthO ) ; 最好把 lambda 表达式看作是一 个函数 , 而不是一个对象 , 另外要接受 lambda 表达式可以传递到函数式接口 。

内部类

内部类 ( inner class ) 是定义在另一个类中的类 。 为什么需要使用内部类呢 ?  •内部类方法可以访问该类定义所在的作用域中的数据, 包括私有的数据 。 •内部类可以对同一个包中的其他类隐藏起来。 • 当想要定义一个回调函数且不想编写大量代码时 , 使用匿名 ( anonymous ) 内部类比较 便捷 。 在Java中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类。广泛意义上的内部类一般来说包括这四种:成员内部类、局部内部类、匿名内部类和静态内部类。

.匿名内部类

什么是匿名对象?如果一个对象只要使用一次,那么我们就是需要 new Object().method() 。 就可以了,而不需要给这个实例保存到该类型变量中去。这就是匿名对象。
public class Test {
public static void main(String[] args) {
//讲new出来的Apple实例赋给apple变量保存起来,但是我们只需要用一次,就可以这样写
Apple apple = new Apple();
apple.eat();
//这种就叫做匿名对象的使用,不把实例保存到变量中。
new Apple().eat();
}
}
class Apple{
public void eat(){
System.out.println("我要被吃了");
}
}

匿名内部类跟匿名对象是一个道理: 匿名对象:我只需要用一次,那么我就不用声明一个该类型变量来保存对象了, 匿名内部类:我也只需要用一次,那我就不需要在类中先定义一个内部类,而是等待需要用的时候,我 就在临时实现这个内部类,因为用次数少,可能就这一次,那么这样写内部类,更方便。不然先写出一 个内部类的全部实现来,然后就调用它一次,岂不是用完之后就一直将其放在那,那就没必要那样。 1. 匿名内部类需要依托于其他类或者接口来创建 如果依托的是类 , 那么创建出来的匿名内部类就默认是这个类的子类 如果依托的是接口 , 那么创建出来的匿名内部类就默认是这个接口的实现类。 2. 匿名内部类的声明必须是在使用 new 关键字的时候 匿名内部类的声明及创建对象必须一气呵成 , 并且之后能反复使用 , 因为没有名字。  
public static void main(String[] args) {
//如果我们需要使用接口中的方法,我们只需要走一步,就是使用匿名内部类,直接将其
类的对象创建出来。
new Test1(){
public void method(){
System.out.println("实现了Test接口的方法");
}
}.method();
}
}
interface Test1{
public void method();
}



上一篇:lambda矩阵的行列式因子


下一篇:Lambda CrossJoin