6.1 接口 - 6.3 lambda表达式
6.1 接口
接口概念
接口是对类的一组需求描述,这些类要遵从接口描述的统一格式进行定义。设计目的是解决多继承的问题
接口中所有方法时 public 不用现实声明
java.lang.Comparable <T> 有方法
int compareTo(T other) 当前对象与 other 比较,对象小于 other 则返回负值;相等则返回 0 ;否则返回正值。
java.util.Arrays 有方法
static void sort(Object[] a) 使用 mergesort 算法对数组中的元素进行排序。要求数组中的元素属于实现了 Compareable 接口的类,并且元素之间是可比较的。
语言标准规定:对于任意的 x 和 y ,实现必须能够保证 sgn(x.compareTo(y)) = -sgn(y.compareTo(x))。(也就是说,如果 y.compareTo(x) 抛出一个异常,那么x.compareTo(y) 也应该抛出一个异常。)这里的“sgn”是一个数值的符号:如果 n 是负值,sgn(n) 等于-1;如果 n 是0,sgn(n) 等于0;如果 n 是正值,sgn(n)等于1简单地讲,如果调换compareTo的参数,结果的符号也应该调换(而不是实际值)
与 equals 方法一样,在继承过程中有可能会出现问题,因为涉及到子类与父类比较,子类之间的比较。可以在比较对象前,检查是否属于同一类。或者在父类中将比较方法定义为 final,不允许子类覆盖。
接口特性
接口不能实例化,但可以声明变量引用实体类的对象。接口中不能包含实例域,可以包含常量。 接口中的域自带 public static final。 可以使用静态方法,用来替代伴随工具类。
默认方法
default 方法可以在接口内添加方法的具体实现。默认方法的一个重要用途是接口演化,给已经被使用的接口添加方法时,如果没有提供默认实现,则实现此接口的类必须去实现新的方法,破坏了兼容性。
默认方法与基类的方法冲突时,同名且有相同类型参数的默认方法会被忽略。
如果一个超接口提供了一个默认方法,另一个接口提供了一个同名而且参数类型 (不论是否是默认参数)相同的方法, 必须覆盖这个方法来解决冲突。
两个接口如何冲突并不重要。 如果至少有一个接口提供了一个实现, 编译器就会报告错误, 而程序员就必须解决这个二义性。
6.2 接口示例
回调
一种程序设计模式,可以指出某个特定事件发生时应该采取的动作。
public class TimePrinter implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("At the tone, the time is "+new Date());
Toolkit.getDefaultToolkit().beep();
}
}
TimePrinter 实现了接口 ActionListener 实现了 actionPerformed 方法,即告诉程序发生了某件事调用了这个方法时,进行如何操作。
Comparator 接口
有的时候需要自定义一些比较规则用于数组排序 Arrays.sort(T[] a, Comparator<? super T> c)
则可以定义一个类实现 Comparator 接口,实现 compara 方法
对象克隆
Object 实现 clone 方法,只是一个个域进行拷贝。如果对象中所有的域都是基本类型,拷贝没有问题。但如果对象包含子对象的引用,拷贝域则会得到相同对象的另一个引用。这样一来,克隆与原对象仍然会共享一些信息。 如果共享的子对象是不可改变的,这种共享是安全的。或者在对象生命周期中,子对象所包含的都是不变的常量。
但是通常情况下,子对象都是可变的,必须重新定义 clone 方法来建立一个深拷贝,同时克隆所有子对象。如果需要使用 clone 方法,必须实现 Cloneable 接口,重新定义 clone 方法,并指定访问权限为 public。
即使 clone 的默认实现能够满足要求,还是需要实现 Cloneable 接口,将 clone 重新定义为 public ,再调用 super.clone()。
6.3 Lambda 表达式
将一个代码块传递到某个对象,代码块将在未来某个时候调用。Java 中传递一段代码并不容易,不能直接传递代码段,必须构造一个对象,这个对象的类需要有一个方法能包含所需的代码。
lambda 表达式语法
lambda 表达式就是一个代码块,以及必须传入代码的变量规范。
参数,箭头(->)以及一个表达式。如果代码要完成的计算无法放到一个表达式中,可以像写方法一样,把代码放到{}中并包含显式的 return 语句。
即使没有参数仍然要提供空括号,如果能推导出一个 lambda 表达式的参数类型,则可以忽略其类型。如果方法只有一个参数,且参数类型可以推导出来,小括号也可以省略。无需指定 lambda 表达式的返回类型,lambda 表达式的返回类型总是会由上下文推导得出。
函数式接口
对于只有一个抽象方法的接口,需要这种接口的对象时,就可以提供一个 lambda 表达式。这种接口称为函数式接口(functional interface)
通常遇到方法需要一个标记接口为参数时,会创建一个类去实现接口,再用接口类型的变量引用类的对象作为参数。更直接一点的办法是,使用一个匿名类实现接口,并实现方法。而使用 lambda表达式则直接传入方法,对应的就是函数式接口的那个方法的实现。
方法引用
例如下面代码的 lambda 表达式是等价的,System.out::println 是方法引用。
Timer t = new Timer(1000,event -> System.out.println(event));
Timer t1 = new Timer(1000,System.out::println);
要用 :: 操作符分隔方法名与对象或类名。主要有 3 种情况:
- object::instanceMethod
- Class::staticMethod
- Class::instanceMethod
前两种情况中,方法引用等价于提供参数的 lambda 表达式。例如
System.out::println //等价于 x -> System.outprintln(x)
Math::pow //等价于(x,y) ->Math.pow(x,y)
第三种情况,第 1 个参数会成为方法的目标。例如
String::compareToIngoreCase //等价于(x,y) ->x.compareToIgnoreCase(y)
可以在方法引用中使用 this 例如
this::equal //等价于 x ->this.equal(x)。
使用 super 也是合法的。
构造器引用
与方法引用类似,不过方法名为new
int[]::new //等价于 x-> new int[x]
变量作用域
lambda 表达式可以捕获外围作用域中变量的值。在 Java 中,要确保所捕获的值是明确定义的,有一个限制,即 lambda 表达式中只能引用不会改变的变量。lambda 表达式中捕获的变量必须实际上是最终变量,即变量初始化后不会再为它赋值。
处理 lambda 表达式
使用 lambda表达式的重点是延迟执行。方法在被当做函数时接口调用时才会执行。可能有下列原因需要延迟执行
- 在一个单独的线程中运行代码
- 多次运行代码
- 在算法的适当位置运行代码
- 发生某种情况时执行代码
- 只在必要时才运行代码
下表是常用的函数式接口
| 函数式接口 | 参数类型 | 返回类型 | 抽象方法名 | 描述 | 其他方法 |
|---|---|---|---|---|---|
| Runnable | 无 | void | run | 作为无参数或返回值的动作运行 | |
| Supplier<T> | 无 | T | get | 提供一个 T 类型的值 | |
| Consumer<T> | T | void | accept | 提供一个 T 类型的值 | andThen |
| BiConsumer<T,U> | T,U | void | accept | 处理 T 和 U 类型的值 | andThen |
| Function<T,R> | T | R | apply | 有一个 T 类型参数的函数 | compose, andThen, identity |
| BiFunction<T,U,R> | T,U | R | apply | 有 T 和 U 类型参数的函数 | andThen |
| UnaryOperation<T> | T | T | apply | 类型 T 上的一元操作符 | compose, andThen, identity |
| BinaryOperatior<T> | T,T | T | apply | 类型 T 上的二元操作符 | andThen, maxBy, minBy |
| Predicate<T> | T | boolean | test | 布尔值函数 | and, or, negate, isEqual |
| BiPredicate<T> | T,U | boolean | test | 有两个参数的布尔值函数 | and, or, negate |
6.1 接口 - 6.3 lambda表达式的更多相关文章
- [二] java8 函数式接口详解 函数接口详解 lambda表达式 匿名函数 方法引用使用含义 函数式接口实例 如何定义函数式接口
函数式接口详细定义 package java.lang; import java.lang.annotation.*; /** * An informative annotation type use ...
- Java1.8新特性——接口改动和Lambda表达式
Java1.8新特性——接口改动和Lambda表达式 摘要:本文主要学习了Java1.8的新特性中有关接口和Lambda表达式的部分. 部分内容来自以下博客: https://www.cnblogs. ...
- Lambda表达式与函数式接口
Lambda表达式的类型,也被称为目标类型(targer type),Lambda表达式的目标类型必须是"函数式接口(functional interface)".函数式接口代表只 ...
- java8 Lambda表达式的新手上车指南(1)--基础语法和函数式接口
背景 java9的一再推迟发布,似乎让我们恍然想起离发布java8已经过去了三年之久,java8应该算的上java语言在历代版本中变化最大的一个版本了,最大的新特性应该算得上是增加了lambda表达式 ...
- Java核心技术-接口、lambda表达式与内部类
本章将主要介绍: 接口技术:主要用来描述类具有什么功能,而并不给出每个功能的具体实现.一个类可以实现一个或多个接口. lambda表达式:这是一种表示可以在将来的某个时间点执行的代码块的简洁方法. 内 ...
- java8函数式接口详解、函数接口详解、lambda表达式匿名函数、方法引用使用含义、函数式接口实例、如何定义函数式接口
函数式接口详细定义 函数式接口只有一个抽象方法 由于default方法有一个实现,所以他们不是抽象的. 如果一个接口定义了一个抽象方法,而他恰好覆盖了Object的public方法,仍旧不算做接口的抽 ...
- 函数式接口 & lambda表达式 & 方法引用
拉呱: 终于,学习jdk8的新特性了,初体验带给我的感觉真爽,代码精简的不行,可读性也很好,而且,spring5也是把jdk8的融入到血液里,总之一句话吧,说的打趣一点,学的时候自己难受,学完了写出来 ...
- java8 Lambda 表达式和函数式接口快速理解
前言 接上篇文章 java8 新特性 由于上篇过于庞大,使得重点不够清晰,本篇单独拿出 java8 的 Lambda 表达式和函数式接口说明. Lambda 表达式 lambda 表达式其实就是使用了 ...
- 死磕Lambda表达式(四):常用的函数式接口
失去人性,失去很多:失去兽性,失去一切.--<三体> 在Java8支持Lambda表达式以后,为了满足Lambda表达式的一些典型使用场景,JDK为我们提供了大量常用的函数式接口.它们主要 ...
随机推荐
- C++枚举变量与switch
转载:https://www.cnblogs.com/banmei-brandy/p/11263927.html 枚举类型和变量如何定义,下篇博客讲得十分详细: https://blog.csdn.n ...
- vue中解决chrome浏览器自动播放音频 和MP3语音打包到线上
一.vue中解决chrome浏览器自动播放音频 需求 有新订单的时候,页面自动语音提示和弹出提示框: 问题 chrome浏览器在18年4月起,就在桌面浏览器全面禁止了音视频的自动播放功能.严格地来说, ...
- windows server2008 r2激活
KMS激活: 管理员运行cmd 输入以下命令 slmgr /ipk 密钥slmgr /skms zh.us.toslmgr /atoslmgr /xpr 可用密钥如下: KMS Windows Ser ...
- 非阻塞I/O和阻塞I/O
1.简介 等待队列实现在事件上的条件等待:希望等待特定事件的进程把自己放进合适的等待队列,并放弃控制权.可用于: - 中断处理 - 进程同步 - 定时 2.等待队列头数据结构 1 typedef st ...
- 实现base64的编码解码,深刻理解base64
上代码 #include<stdio.h> #include<string.h> #include<stdlib.h> const char padding = ' ...
- 网络最大流Dinic
1.什么是网络最大流 形象的来说,网络最大流其实就是这样一个生活化的问题:现在有一个由许多水管组成的水流系统,每一根管道都有自己的最大通过水流限制(流量),超过这个限制水管会爆(你麻麻就会来找你喝茶q ...
- pytest文档33-Hooks函数获取用例执行结果(pytest_runtest_makereport)
前言 pytest提供的很多钩子(Hooks)方法方便我们对测试用例框架进行二次开发,可以根据自己的需求进行改造. 先学习下pytest_runtest_makereport这个钩子方法,可以更清晰的 ...
- 每个人都可以用C语言写的推箱子小游戏!今天你就可以写出属于自己项目~
C语言,作为大多数人的第一门编程语言,重要性不言而喻,很多编程习惯,逻辑方式在此时就已经形成了.这个是我在大一学习 C语言 后写的推箱子小游戏,自己的逻辑能力得到了提升,在这里同大家分享这个推箱子小游 ...
- 【迷宫问题】CodeForces 1292A A NEKO's Maze Game
题目大意 vjudge链接 共两行,从(1,n)到(2,n). 每过一个时刻会有一个位置的状态变化,从能到达这个位置变成不能到达,或从不能到达变成能到达,问在每个时刻中是否能从起点到终点. 数据范围 ...
- pmm-server 搭建
1 搭建docker centos 下 参考文档搭建docker https://www.cnblogs.com/brady-wang/p/11543237.html docker create \ ...