Lambda表达式
1.Lambda表达式
1.1 函数式编程思想概述
public class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("多线程程序启动了");
}
}
/*
需求:启动一个线程,在控制台输出一句话:多线程程序启动了
*/
public class LambdaDemo {
public static void main(String[] args) {
//实现类的方式实现需求
// MyRunnable my = new MyRunnable();
// Thread t = new Thread(my);
// t.start();
//匿名内部类的方式改进
// new Thread(new Runnable() {
// @Override
// public void run() {
// System.out.println("多线程程序启动了");
// }
// }).start();
//Lambda表达式的方式改进
new Thread( () -> {
System.out.println("多线程程序启动了");
} ).start();
}
}
1.2 Lambda表达式的标准格式
1.2.1 Lambda表达式练习1(抽象方法无参无返回值)
Eatable
public interface Eatable {
void eat();
}
EatableImpl
public class EatableImpl implements Eatable {
@Override
public void eat() {
System.out.println("一天一苹果,医生远离我");
}
}
EatableDemo
/*
Lambda表达式的格式:(形式参数) -> {代码块}
练习1:
1:定义一个接口(Eatable),里面定义一个抽象方法:void eat();
2:定义一个测试类(EatableDemo),在测试类中提供两个方法
一个方法是:useEatable(Eatable e)
一个方法是主方法,在主方法中调用useEatable方法
*/
public class EatableDemo {
public static void main(String[] args) {
//在主方法中调用useEatable方法
Eatable e = new EatableImpl();//多态实现接口
useEatable(e);
//匿名内部类
useEatable(new Eatable() {
@Override
public void eat() {
System.out.println("匿名内部类:一天一苹果,医生远离我");
}
});
//Lambda表达式
useEatable(() -> {
System.out.println("Lambda表达式:一天一苹果,医生远离我");
});
}
private static void useEatable(Eatable e) {
e.eat();
}
}
1.2.2 Lambda表达式练习2(抽象方法带参无返回值)
Flyable
public interface Flyable {
void fly(String s);
}
FlyableDemo
/*
Lambda表达式的格式:(形式参数) -> {代码块}
练习2:
1:定义一个接口(Flyable),里面定义一个抽象方法:void fly(String s);
2:定义一个测试类(FlyableDemo),在测试类中提供两个方法
一个方法是:useFlyable(Flyable f)
一个方法是主方法,在主方法中调用useFlyable方法
*/
public class FlyableDemo {
public static void main(String[] args) {
//在主方法中调用useFlyable方法
//匿名内部类
useFlyable(new Flyable() {
@Override
public void fly(String s) {
System.out.println(s);
System.out.println("飞机自驾游");
}
});
System.out.println("--------");
//Lambda
useFlyable((String s) -> {
System.out.println(s);
System.out.println("飞机自驾游");
});
}
private static void useFlyable(Flyable f) {
f.fly("风和日丽,晴空万里");
}
}
1.2.3 Lambda表达式练习3(抽象方法带参有返回值)
public interface Addable {
int add(int x,int y);
}
/*
Lambda表达式的格式:(形式参数) -> {代码块}
练习3:
1:定义一个接口(Addable),里面定义一个抽象方法:int add(int x,int y);
2:定义一个测试类(AddableDemo),在测试类中提供两个方法
一个方法是:useAddable(Addable a)
一个方法是主方法,在主方法中调用useAddable方法
*/
public class AddableDemo {
public static void main(String[] args) {
//在主方法中调用useAddable方法
useAddable((int x,int y) -> {
return x + y;
// return x - y;
});
}
private static void useAddable(Addable a) {
int sum = a.add(10, 20);
System.out.println(sum);
}
}
1.2.4 Lambda表达式的省略模式
Addable
public interface Addable {
int add(int x, int y);
}
Flyable
public interface Flyable {
void fly(String s);
}
/*
Lambda表达式的省略模式
*/
public class LambdaDemo {
public static void main(String[] args) {
// useAddable((int x,int y) -> {
// return x + y;
// });
//参数的类型可以省略
useAddable((x, y) -> {
System.out.print("参数的类型可以省略(两个参数):");
return x + y;
});
//但是有多个参数的情况下,不能只省略一个
// useAddable((x,int y) -> {
// return x + y;
// });
// useFlyable((String s) -> {
// System.out.println(s);
// });
useFlyable((s) -> {
System.out.println("参数的类型可以省略(一个参数):"+s);
});
//如果参数有且仅有一个,那么小括号可以省略
useFlyable(s -> {
System.out.println(s);
});
//如果代码块的语句只有一条,可以省略大括号和分号
useFlyable(s -> System.out.println("参数的类型可以省略(一个参数)+省略大括号和分号:"+s));
//如果代码块的语句只有一条,可以省略大括号和分号,如果有return,return也要省略掉
System.out.print("省略大括号和分号,return也要省略掉:");
useAddable((x, y) -> x + y);
}
private static void useFlyable(Flyable f) {
f.fly("风和日丽,晴空万里");
}
private static void useAddable(Addable a) {
int sum = a.add(10, 20);
System.out.println(sum);
}
}
1.3 Lambda表达式的注意事项
public interface Inter {
void show();
// void method();
}
/*
Lambda表达式的注意事项
*/
public class LambdaDemo {
public static void main(String[] args) {
// useInter(() -> {
// System.out.println("好好学习天天向上");
// });
//使用Lambda必须要有接口,并且要求接口中有且仅有一个抽象方法
useInter(() -> System.out.println("好好学习天天向上"));
//必须有上下文环境,才能推导出Lambda对应的接口
// new Thread(new Runnable() {
// @Override
// public void run() {
// System.out.println("匿名内部类");
// }
// }).start();
// Runnable r = () -> System.out.println("Lambda表达式");
// new Thread(r).start();
new Thread(() -> System.out.println("Lambda表达式")).start();
}
private static void useInter(Inter i) {
i.show();
}
}
1.4 Lambda表达式和匿名内部类的区别
public interface Inter {
void show();
// void show2();
}
public abstract class Animal {
public abstract void method();
}
public class Student {
public void study() {
System.out.println("爱生活,爱Java");
}
}
/*
Lambda表达式和匿名内部类的区别
*/
public class LambdaDemo {
public static void main(String[] args) {
//匿名内部类
useInter(new Inter() {
@Override
public void show() {
System.out.println("匿名内部类+接口");
}
});
useAnimal(new Animal() {
@Override
public void method() {
System.out.println("匿名内部类+抽象类");
}
});
useStudent(new Student(){
@Override
public void study() {
System.out.println("匿名内部类+具体类");
}
});
useInter(new Inter() {
@Override
public void show() {
System.out.println("匿名内部类+接口(接口中只能有一个方法)");
}
});
//Lambda
useInter(() -> System.out.println("Lambda+接口"));
// useAnimal(() -> System.out.println("抽象类"));//Lambda只能用于接口
// useStudent(() -> System.out.println("具体类"));Lambda只能用于接口
// useInter(() -> System.out.println("接口"));
// useInter(new Inter() {//若接口中有多个方法,匿名内部类要重写多个方法
// @Override
// public void show() {
// System.out.println("show");
// }
//
// @Override
// public void show2() {
// System.out.println("show2");
// }
// });
}
private static void useStudent(Student s) {
s.study();
}
private static void useAnimal(Animal a) {
a.method();
}
private static void useInter(Inter i) {
i.show();
}
}
2.接口组成更新
2.1 接口组成更新概述
2.2 接口中默认方法
MyInterface
public interface MyInterface {
void show1();
void show2();
// void show3();
// public default void show3() {
// System.out.println("show3");
// }
default void show3() {
System.out.println("show3");
}
}
MyInterfaceSon
public interface MyInterfaceSon extends MyInterface {
void show3();
}
MyInterfaceImplOne
public class MyInterfaceImplOne implements MyInterface {
@Override
public void show1() {
System.out.println("One show1");
}
@Override
public void show2() {
System.out.println("One show2");
}
// @Override
// public void show3() {
// System.out.println("One show3");
// }//不强制重写,但可以重写
}
MyInterfaceImplTwo
public class MyInterfaceImplTwo implements MyInterface {
@Override
public void show1() {
System.out.println("Two show1");
}
@Override
public void show2() {
System.out.println("Two show2");
}
}
MyInterfaceDemo
/*
需求:
1:定义一个接口MyInterface,里面有两个抽象方法:
void show1();
void show2();
2:定义接口的两个实现类:
MyInterfaceImplOne
MyInterfaceImplTwo
3:定义测试类:
MyInterfaceDemo
在主方法中,按照多态的方式创建对象并使用
*/
public class MyInterfaceDemo {
public static void main(String[] args) {
//按照多态的方式创建对象并使用
MyInterface my = new MyInterfaceImplOne();
my.show1();
my.show2();
my.show3();
}
}
2.3 接口中静态方法
Inter
public interface Inter {
void show();
default void method(){
System.out.println("Inter 中的默认方法执行了");
}
// public static void test(){
// System.out.println("Inter 中的静态方法执行了");
// }
static void test(){
System.out.println("Inter 中的静态方法执行了");
}
}
Flyable
public interface Flyable {
public static void test() {
System.out.println("Flyable 中的静态方法执行了");
}
}
InterImpl
public class InterImpl implements Inter,Flyable {
@Override
public void show() {
System.out.println("show方法执行了");
}
}
InterDemo
/*
需求:
1:定义一个接口Inter,里面有三个方法:一个是抽象方法,一个是默认方法,一个是静态方法
void show();
default void method(){ }
public static void test(){ }
2:定义接口的一个实现类:
InterImpl
3:定义测试类:
InterDemo
在主方法中,按照多态的方式创建对象并使用
*/
public class InterDemo {
public static void main(String[] args) {
//按照多态的方式创建对象并使用
Inter i = new InterImpl();
i.show();
i.method();
// i.test();//静态方法只能通过接口名调用
Inter.test();
// InterImpl.test();
Flyable.test();
}
}
2.4 接口中私有方法
Inter
public interface Inter {
default void show1() {//默认方法
System.out.println("show1开始执行");
// System.out.println("初级工程师");
// System.out.println("中级工程师");
// System.out.println("高级工程师");
// show();
method();
System.out.println("show1结束执行");
}
default void show2() {//默认方法,可以调用私有静态方法和私有非静态方法
System.out.println("show2开始执行");
// System.out.println("初级工程师");
// System.out.println("中级工程师");
// System.out.println("高级工程师");
// show();
method();
System.out.println("show2结束执行");
}
private void show() {//私有非静态方法
System.out.println("初级工程师");
System.out.println("中级工程师");
System.out.println("高级工程师");
}
static void method1() {//静态方法,只能调用私有静态方法
System.out.println("method1开始执行");
// System.out.println("初级工程师");
// System.out.println("中级工程师");
// System.out.println("高级工程师");
// show();
method();
System.out.println("method1结束执行");
}
static void method2() {//静态方法
System.out.println("method2开始执行");
// System.out.println("初级工程师");
// System.out.println("中级工程师");
// System.out.println("高级工程师");
method();
System.out.println("method2结束执行");
}
private static void method() {//私有静态方法
System.out.println("初级工程师");
System.out.println("中级工程师");
System.out.println("高级工程师");
}
}
InterImpl
public class InterImpl implements Inter {
}
InterDemo
/*
需求:
1:定义一个接口Inter,里面有四个方法:二个默认方法,二个静态方法
default void show1(){ }
default void show2(){ }
static void method1(){ }
static void method2(){ }
2:定义接口的一个实现类:
InterImpl
3:定义测试类:
InterDemo
在主方法中,按照多态的方式创建对象并使用
*/
public class InterDemo {
public static void main(String[] args) {
//按照多态的方式创建对象并使用
Inter i = new InterImpl();
i.show1();
System.out.println("--------");
i.show2();
System.out.println("--------");
Inter.method1();
System.out.println("--------");
Inter.method2();
}
}
3.方法引用
3.1 方法引用符
Printable
public interface Printable {
void printInt(int i);
}
PrintableDemo
/*
需求:
1:定义一个接口(Printable):里面定义一个抽象方法:void printInt(int i);
2:定义一个测试类(PrintableDemo),在测试类中提供两个方法
一个方法是:usePrintable(Printable p)
一个方法是主方法,在主方法中调用usePrintable方法
*/
public class PrintableDemo {
public static void main(String[] args) {
//在主方法中调用usePrintable方法
usePrintable(i -> System.out.println(i));
//方法引用
usePrintable(System.out::println);
}
private static void usePrintable(Printable p) {
p.printInt(666);
}
}
3.2 Lambda表达式支持的方法引用
3.2.1 引用类方法
Converter
public interface Converter {
int convert(String s);
}
ConverterDemo
/*
练习:
1:定义一个接口(Converter),里面定义一个抽象方法:
int convert(String s);
2:定义一个测试类(ConverterDemo),在测试类中提供两个方法
一个方法是:useConverter(Converter c)
一个方法是主方法,在主方法中调用useConverter方法
*/
public class ConverterDemo {
public static void main(String[] args) {
//在主方法中调用useConverter方法
// useConverter((String s) -> {
// return Integer.parseInt(s);
// });
useConverter(s -> Integer.parseInt(s));
//引用类方法
useConverter(Integer::parseInt);
//Lambda表达式被类方法替代的时候,它的形式参数全部传递给静态方法作为参数
}
private static void useConverter(Converter c) {
int number = c.convert("666");
System.out.println(number);
}
}
3.2.2 引用对象的实例方法
Printer
public interface Printer {
void printUpperCase(String s);
}
PrintString
public class PrintString {
//把字符串参数变成大写的数据,然后在控制台输出
public void printUpper(String s) {
String result = s.toUpperCase();
System.out.println(result);
}
}
PrinterDemo
/*
练习
1:定义一个类(PrintString),里面定义一个方法
public void printUpper(String s):把字符串参数变成大写的数据,然后在控制台输出
2:定义一个接口(Printer),里面定义一个抽象方法
void printUpperCase(String s)
3:定义一个测试类(PrinterDemo),在测试类中提供两个方法
一个方法是:usePrinter(Printer p)
一个方法是主方法,在主方法中调用usePrinter方法
*/
public class PrinterDemo {
public static void main(String[] args) {
//在主方法中调用usePrinter方法
// usePrinter((String s) -> {
String result = s.toUpperCase();
System.out.println(result);
// System.out.println(s.toUpperCase());
// });
usePrinter(s -> System.out.println(s.toUpperCase()));
//引用对象的实例方法
PrintString ps = new PrintString();
usePrinter(ps::printUpper);
//Lambda表达式被对象的实例方法替代的时候,它的形式参数全部传递给该方法作为参数
}
private static void usePrinter(Printer p) {
p.printUpperCase("HelloWorld");
}
}
3.2.3 引用类的实例方法
//Lambda表达式被类的实例方法替代的时候
//第一个参数作为调用者
//后面的参数全部传递给该方法作为参数
MyString
public interface MyString {
String mySubString(String s,int x,int y);
}
MyStringDemo
/*
练习
1:定义一个接口(MyString),里面定义一个抽象方法:
String mySubString(String s,int x,int y);
2:定义一个测试类(MyStringDemo),在测试类中提供两个方法
一个方法是:useMyString(MyString my)
一个方法是主方法,在主方法中调用useMyString方法
*/
public class MyStringDemo {
public static void main(String[] args) {
//在主方法中调用useMyString方法
// useMyString((String s,int x,int y) -> {
// return s.substring(x,y);
// });
useMyString((s,x,y) -> s.substring(x,y));
//引用类的实例方法
useMyString(String::substring);
//Lambda表达式被类的实例方法替代的时候
//第一个参数作为调用者
//后面的参数全部传递给该方法作为参数
}
private static void useMyString(MyString my) {
String s = my.mySubString("HelloWorld", 2, 5);
System.out.println(s);
}
}
3.2.4 引用构造器
Student
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
StudentBuilder
public interface StudentBuilder {
Student build(String name,int age);
}
StudentDemo
/*
练习
1:定义一个类(Student),里面有两个成员变量(name,age)
并提供无参构造方法和带参构造方法,以及成员变量对应的get和set方法
2:定义一个接口(StudentBuilder),里面定义一个抽象方法
Student build(String name,int age);
3:定义一个测试类(StudentDemo),在测试类中提供两个方法
一个方法是:useStudentBuilder(StudentBuilder s)
一个方法是主方法,在主方法中调用useStudentBuilder方法
*/
public class StudentDemo {
public static void main(String[] args) {
//在主方法中调用useStudentBuilder方法
// useStudentBuilder((String name,int age) -> {
Student s = new Student(name,age);
return s;
// return new Student(name,age);
// });
useStudentBuilder((name,age) -> new Student(name,age));
//引用构造器
useStudentBuilder(Student::new);
//Lambda表达式被构造器替代的时候,它的形式参数全部传递给构造器作为参数
}
private static void useStudentBuilder(StudentBuilder sb) {
Student s = sb.build("林青霞", 30);
System.out.println(s.getName() + "," + s.getAge());
}
}