typora-copy-images-to: imgs
今日内容一
- 回顾接口 (掌握)
- Lambda表达式 (理解并掌握)
一.回顾接口(掌握)
-
需求:已经知道有一个接口,想调用接口中的方法
-
如何实现:
-
方式一:定义一个类,实现该接口,重写接口中的方法。
接口 对象 = new 实现类();
对象调用方法。
-
方式二:直接通过匿名内部类的方式实现的。
接口 对象 = new 接口(){};
-
方式三:通过lambda表达式实现的。
-
-
演示代码
package lession; public class Demo1 { public static void main(String[] args){ //1.创建对象: 通过lambda表达式实现 //lambda表达式基本语法: //1. () 来定义接口方法的形式参数 //2. {} 来定义接口中的方法体 //3. -> 将(形式参数)--->{方法体} 构建联系关系 A a = ()->{ System.out.println("测试方法11111"); }; //2.使用对象调用方法 a.test(); } //方式二: 通过子类来创建对象,调用方法 private static void test2(){ //1. 通过子类来创建对象 A a = new SonA(); //2. 通过对象来调用方法 a.test(); } //1.方式一:通过匿名内部类来创建对象,调用接口中的方法 private static void test(){ //需求: 调用接口中的test方法 //1.通过匿名内部类创建对象 A a = new A() { @Override public void test(){ System.out.println("测试方法"); } }; //2.通过对象来调用方法 a.test(); } } //1.提供接口 interface A{ void test(); } //2.提供一个实现类 class SonA implements A{ public void test(){ System.out.println("子类进行测试方法"); } }
总结:
函数式编程概述:
函数式编程是种编程方式,它将电脑运算视为函数的计算。函数编程语言最重要的基础是λ演算(lambda calculus),而且λ演算的函数可以接受函数当作输入(参数)和输出(返回值) 。
一句话总结: lambda表达式来替代匿名内部类(替代函数式接口),进行函数式输入和输出运算.
- lambda表达式输入: 通过前面的小括号进行参数传递,实现输入
- lambda表达式输出: 通过后面的大括号的方法体,进行数据的返回.
通过lambda表达式的写法,其实就是函数式编程思想的体现。
特点:
- 不用关注具体的实现过程(不用给接口提供实现类),关注方法实现结果就可以了。
- 在函数式编程中,lambda表达式可以作为参数使用(替代函数式接口,或者说替代匿名内部类)。
注意:
lambda表达式在函数式编程中,可以替代接口,要求该接口必须是函数式接口。
函数式接口特点:有且仅有一个抽象方法。
区分是不是函数式接口:
标记了@FunctionalInterface注解的接口都是函数式接口。
二.Lambda表达式(理解和掌握)
2.1 基本语法
语法格式: (参数列表)->{方法体}
注意:
-
(参数列表):对应接口中方法的形式参数。
-
{方法体}: 具体的方法实现效果,其实就是方法体.
-
比如:
public String test(int a, String b){ String str = a+b; return str; } //方法的形参: a, b //方法体: String str = a+b; return str; //lambda表达式书写: (int a,String b)->{ // int a, String b 就是lambda表达式的输入(把参数传递给方法体去使用) String str= a+b; return str;// str 就是lambda表达式的输出(使用参数完毕后,返回值) };
2.2 作用
Lambda表达式的作用:替代函数式接口(替代匿名内部类的)。
应用场景有两个地方:
- 使用lambda给接口创建对象.
- 在方法的参数里面使用lambda表达式(前提方法的参数是函数式接口)
- 一句话总结: Lambda表达式的作用不就是替代匿名内部类的
优点:简化接口的开发(不用关注接口的具体实现,简化开发)。
应用场景如下:
package lession2;
/**
* 演示: lambda表达式的应用场景, 具体指的在两个地方使用
* 1. 使用lambda给接口创建对象.
* 2. 在方法的参数里面使用lambda表达式(前提方法的参数是函数式接口)
*/
public class Demo2 {
public static void main(String[] args){
//需求1: 不使用lambda调用接口中的方法
/* C cc = new C() {
@Override
public void test(int a){
System.out.println("打印数据:"+a);
}
};
cc.test(100);//输入*/
//需求2 : 使用lambda给接口创建对象.
C cc = (int a)->{System.out.println(a);};
//cc.test(2000);//输入
//需求2 : 在方法的参数里面使用lambda表达式(前提方法的参数是函数式接口)
//---------1.使用匿名内部类创建对象,传递到方法中------------------
C cc2 = new C() {
@Override
public void test(int a){
System.out.println(a);
}
};
operationData(10101,cc2);
//--------2.先使用lambda表达式创建对象,传递到方法中------------
C cc3 = (int a)->{
System.out.println(a);
};
operationData(301301,cc3);
//---------3.直接将lambda表达式传体到方法中-----------------
operationData(401401,(int a)->{
System.out.println(a);
});
//----------------------------------
}
public static void operationData(int a, C cc){
cc.test(a);
}
}
interface C{
void test(int a);
}
2.3 具体应用
注意:Lambda表达式 替代函数式接口(函数式接口里面有且仅有一个抽象方法)
- 1.替换函数式接口:没有参数没有返回值的方法,如:()->{方法体}
package lession2;
/**
* 演示:1.函数式接口:没有参数没有返回值的方法
*/
public class Demo1 {
public static void main(String[] args) {
//方式一:自定义类实现接口,创建对象
show(new Zi22());
//方式二:匿名内部类的方式,创建对象
show(new MyInterface2() {
@Override
public void test() {
System.out.println("匿名内部类的方式test---");
}
});
//方式三:lambda表达式的写法,(参数列表)->{方法体}
show(()->{System.out.println("lambda的方式test---");});
}
//1.提供一个方法:传递对象,调用接口中的方法
public static void show(MyInterface2 m){
m.test();
}
}
@FunctionalInterface
interface MyInterface2{
void test();
}
class Zi22 implements MyInterface2{
@Override
public void test() {
System.out.println("子类实现接口的test方法---");
}
}
- 2.替换函数式接口:有参数没有返回值的方法,如:(接口中的参数)->{方法体}
package lession2;
/**
* 演示:2.替换函数式接口:有参数没有返回值的方法,如:(接口中的参数)->{方法体}
*/
public class Demo2 {
public static void main(String[] args) {
//1.方式一:自定义类创建对象
show(new ZiImpl3());// MyInterface3 m3 = new ZiImpl3();
//2.方式二:匿名内部类创建对象
show(new MyInterface3() {
@Override
public void test(String name) {
System.out.println("匿名内部类,传递参数:" + name);
}
});
//3.方式三:lambda
show((name)->{
System.out.println("lambda表达式,传递参数:"+name);
});
}
public static void show(MyInterface3 m3) {
m3.test("YY要下载喔!!!");
}
}
@FunctionalInterface
interface MyInterface3 {
void test(String name);
}
class ZiImpl3 implements MyInterface3 {
@Override
public void test(String name) {
System.out.println("自定义类,传递的参数:" + name);
}
}
- 3.替换函数式接口: 没有参数有返回值的方法,如:()->{方法体; return 值;}
/**
* 演示;3.替换函数式接口: 没有参数有返回值的方法,如:()->{方法体; return 值;}
*/
public class Demo3 {
public static void main(String[] args) {
//1.方式二:匿名内部类的写法
show(new MyInterface4() {
@Override
public String test() {
return "下载YY喔!!!";
}
});
//2.方式三:lambada表达式
show(()->{
System.out.println("lambda表达式写法");
return "下载YY喔!!!";
});
}
public static void show(MyInterface4 m4){
String str = m4.test();
System.out.println("返回值:"+str);
}
}
@FunctionalInterface
interface MyInterface4{
String test();
}
- 4.替换函数式接口: 有参数有返回值的方法,如:(参数列表)->{方法体; return 值;}
/**
* 演示:4.替换函数式接口: 有参数有返回值的方法,如:(参数列表)->{方法体; return 值;}
*/
public class Demo4 {
public static void main(String[] args) {
//1.方式二:匿名内部类
show(new MyInterface5() {
@Override
public int add(int x, int y) {
return x+y;
}
});
//2.方式三:lambda表达式
show((int x2,int y2)->{
System.out.println("lambda表达式");
return x2+y2;
});
}
public static void show(MyInterface5 m5){
int sum = m5.add(1,9);
System.out.println("返回值:"+sum);
}
}
@FunctionalInterface
interface MyInterface5{
public abstract int add(int x,int y);
//public abstract void test();
}
2.4 简写方式
-
1.如果方法里面只有一个参数,可以省略小括号
public class Demo5 { MyInterface6 m6 =(int x)->{ System.out.println("测试---"); }; MyInterface6 m6_1 = x->{//省略小括号 System.out.println("测试---"); }; } interface MyInterface6{ void test(int x); } -
2.lambda表达式里面的参数,可以省略类型,还可以省略小括号
MyInterface6 m6_1 =(x)->{//可以省略类型 System.out.println("测试---"); }; -
3.如果方法体里面,有且仅有一个语句,可以省略大括号
MyInterface6 m6_2 =x-> System.out.println("测试");//可以省略大括号 -
4.如果方法里面,有且仅有一个语句,且是返回值,可以省略大括号,并且省略return
public class Demo5 { MyInterface7 m7 = x->{return 6;}; //返回值 MyInterface7 m7_1 = x-> 6; } interface MyInterface7{ int test(int x); }
2.5 Lambda使用注意事项
-
Lambda表达式是用于替代函数式接口(替代匿名内部类),必须保证该接口里面有且仅有一个抽象方法。
-
Lambda表达式是的使用上下文环境 (以MyInterface7举例)
-
给接口创建对象使用:
比如: MyInterface7 m7 = x->6; //返回值
-
作为参数使用:
show( x->6);
-
2.6 Lambda和匿名内部类区别(理解)
-
区别1: 从jdk版本来说
lambda从jdk8以后才有的,新特性。
匿名内部类:没有版本区别
-
区别2:从使用范围来说
lambda只能替换函数式接口(有且仅有一个抽象方法的接口),
匿名内部类:可以是任何接口,任何类(抽象类和普通类)。
-
区别3:从原理来说 (掌握)
lambda(函数式编程,只关注方法的结果),不会编译对应的class文件(效率高,没有编译过程)。
匿名内部类时,在使用过程中,会编译class文件。
三.接口组成的新特性(更新,理解)
3.1 JDK7之前,接口里面只能写常量值和抽象方法
/**
* 演示:jdk7之前,接口的组成:
* 1.常量
* 2.抽象方法
*/
public class Demo1 {
}
interface MyInterface10{
public static final String TRAFICC_lIGHT_COLOR="RED";//1.定义常量值, public static final可以省略的
public abstract void test10();//2.抽象方法,public abstract可以省略的
}
3.2 JDK8以后(JDK9,JDK10-)接口里面可以写静态方法,默认方法,普通私有方法
-
除了在接口中可以定义常量值和抽象方法(常量值可以直接通过接口调用,不能通过对象调用)
-
在接口中定义静态方法,默认被public修饰,可以直接通过接口调用,不能通过对象调用静态方法
-
在接口中定义默认方法,默认被public修饰,只能通过对象调用默认方法
-
在接口中定义私有方法,只能在接口中调用(从JDK9以后才有的)。
/** * 演示:jdk8以后,接口的组成 * 1. 常量值 * 2.抽象方法 * 3. 静态方法 * 4. 默认方法 * 5. 普通方法: 只能定义私有的普通方法 */ public class Demo3 { public static void main(String[] args) { //1.接口直接调用 常量值 String v = MyInterafce11.COLOR; System.out.println("交通灯的颜色:"+v); //2.获取接口对象 MyInterafce11 m11 = new MyInterafce11() { @Override public void test11() { System.out.println("抽象方法---test11"); } }; m11.test11();//调用抽象方法 //3.调用静态方法 MyInterafce11.test12(); //4.调用默认方法 m11.test13(); //5.调用私有方法 //m11.test14();//报错,因为test14方法,是被private修饰,只能在本类中使用。 } } @FunctionalInterface interface MyInterafce11{ public static final String COLOR="red";//1.常量值,可以通过接口名称直接调用,不能使用对象调用 public abstract void test11();//2.抽象方法 public static void test12(){//3.静态方法: public可以省略的,不能使用对象调用 System.out.println("static----test12"); } public default void test13(){//4.默认方法 ,public可以省略的 System.out.println("default---test13"); } private void test14(){//5.普通的私有方法: System.out.println("普通方法"); } }为什么定义私有方法,如下代码:
public class Demo3 { } /* 1.存在哪些问题? 静态方法和默认方法代码 存在冗余问题(重复问题) 2.如何解决存在的问题 对于存在的冗余代码,可以抽取出来,放在私有方法中。 */ interface MyInterface13{ //1.定义静态方法 public static void test1(){ // System.out.println("aaa"); // System.out.println("bbb"); test666(); System.out.println("static---test1"); } //2.定义默认方法 public default void test2(){ // System.out.println("aaa"); // System.out.println("bbb"); test666(); System.out.println("default-----test2"); } //3.定义私有方法:抽取冗余代码 private static void test666(){ System.out.println("aaa"); System.out.println("bbb"); } }