Java:函式式介面、方法引用
阿新 • • 發佈:2018-12-11
1、函式式介面-概念及格式
函式式介面:有且只有一個抽象方法的介面(可以有其他的方法:預設方法,靜態方法,私有方法…)
2、函式式介面[email protected]註解
1)、在定義函式式介面時,為防止發生定義錯誤,可使用@FunctionalInterface註解,強制按照函式式介面的語法進行檢查,如果語法錯誤,編譯器會編譯錯誤。
@FunctionalInterface
interface IA{//如果此介面不定義任何抽象方法,將會報錯
public void show();
public void show1();//如果此介面定義多個抽象方法,也會報錯
}
3、函式式介面-練習-自定義函式式介面(無參無返回值)
//無參,無返回值的函式式介面
@FunctionalInterface
interface IA{
public void show();
}
public class Demo {
public static void main(String[] args) {
//2.使用Lambda表示式,代替"匿名內部類"
fun(() -> System.out.println("呵呵...."));
}
public static void fun(IA a){
a.show();
}
}
4、函式式介面-練習-自定義函式式介面(有參有返回值)
@FunctionalInterface
interface IA{
public int calc(int a, int b);
}
public class Demo {
public static void main(String[] args) {
//2.使用Lambda
fun((int m, int n) -> {
return m + n;
}, 10, 20);
}
public static void fun(IA a, int x, int y) {
int result = a.calc(x, y);
System.out.println("結果是:" + result);
}
}
5、函數語言程式設計-Lambda的應用-延遲執行
@FunctionalInterface
interface IA{
public String buildString();
}
public class Demo {
public static void main(String[] args) {
String s1 = "日誌級別:1";
String s2 = "異常資訊:NullPointerException";
String s3 = "日期:2018-09-22";
//1.使用匿名內部類的方式
fun(1, new IA(){
@Override
public String buildString() {
System.out.println("執行了....");
return s1 + s2 + s3;
}
});
//2.使用Lambda代替匿名內部類
fun(1,()->{
System.out.println("執行啦.....");
return s1 + s2 + s3;});
}
//一個列印日誌
// public static void fun(int level, String msg) {//原方法
public static void fun(int level, IA a) {//改為介面型別形參
if (level == 1) {//只有級別為1時,才打印日誌--延遲
System.out.println(a.buildString());
}
}
}
6、函數語言程式設計-Lambda的應用-自定義介面-Lambda作為引數和返回值
@FunctionalInterface
interface IA{
public void show();
}
public class Demo {
public static void main(String[] args) {
//Lambda作為形參
f1(() -> System.out.println("呵呵呵"));
//Lambda作為返回值
IA a = f2();
a.show();
}
//作為"形參"
public static void f1(IA ia) {
ia.show();
}
//作為"返回值"
public static IA f2(){
return () -> System.out.println("嘻嘻...");
}
}
函式式介面作為形參時,必須要使用這個介面的實現子類來作為實參,而這個實現子類又必須要重寫介面的抽象方法,所以就可以直接使用Lambda表示式作為實參傳入(做返回值同樣)
7、函數語言程式設計-Lambda的應用-類庫介面-Lambda作為形參和返回值
public class Demo {
public static void main(String[] args) {
//1.Lambda作為形參
f1(()-> System.out.println("執行緒啟動!"));
//2.Lambda作為返回值
Runnable r = f2();
new Thread(r).start();
}
//使用Lambda作為"形參"
public static void f1(Runnable runnable) {
new Thread(runnable).start();
}
//使用Lambda作為"返回值"
public static Runnable f2(){
return () -> System.out.println("執行緒啟動....");
}
}
8、方法引用-使用自定義靜態方法替代Lambda(“引用”理解為“替代”)
方法引用:就是使用已存在的方法替代Lambda表示式
@FunctionalInterface
interface IA{
public void show();
}
public class Demo {
public static void main(String[] args) {
fun(Demo::method);//Demo::method代替:Lambda,Lambda代替:匿名內部類。
fun(Demo::f2);//OK的--靜態方法,必須通過"類名"引用,不能通過"物件名"引用。
fun(Demo::f3);//錯誤的,因為其引數不同
}
public static void fun(IA ia) {
ia.show();
}
//其它方法
public static void method(){
System.out.println("呵呵...");
}
private static void f2(){
System.out.println("嘻嘻....");
}
public static void f3(String s) {
System.out.println(s);
}
}
9、方法引用-使用類庫靜態方法替代Lambda
@FunctionalInterface
interface IA{
//列印一個int陣列的所有元素
public String printArray(int[] arr);
}
public class Demo {
public static void main(String[] args) {
int[] arr = {1432,432,432,4325,424,324,32,54,51,412,35,25,144,3};
//使用匿名內部類
fun(new IA(){
@Override
public String printArray(int[] arr) {
StringBuilder bld = new StringBuilder("[");
for (int i = 0; i < arr.length; i++) {
bld.append(arr[i]);
if (i < arr.length - 1) {
bld.append(" ,");
}else{
bld.append("]");
}
}
return bld.toString();
}
},arr);
//使用Lambda
fun((int[] array) -> {
StringBuilder bld = new StringBuilder("[");
for (int i = 0; i < array.length; i++) {
bld.append(array[i]);
if (i < array.length - 1) {
bld.append(" ,");
} else {
bld.append("]");
}
}
return bld.toString();
}, arr);
//使用Arrays的toString()方法來替代:Lambda
fun(Arrays::toString, arr);
}
//定義方法,可以列印陣列
public static void fun(IA a, int[] arr) {
System.out.println(a.printArray(arr));
}
}
10、方法引用-替代原則
“替代的方法”的形參、返回值型別,必須和被替換的“函式式介面”中的抽象方法一致
11、方法引用-使用物件成員方法替代Lambda
@FunctionalInterface
interface Game{
public void run();
}
class Student{
public void playGame(Game game) {
System.out.println("我開始打遊戲:");
game.run();
}
}
class Teacher{
public void like(){
System.out.println("我喜歡喝茶(我是老師).....");
}
}
public class Demo {
public static void main(String[] args) {
Student stu = new Student();
stu.playGame(()-> System.out.println("王者榮耀開始執行....."));
stu.playGame(()-> System.out.println("我喜歡喝茶...."));
//使用Teacher類的like()方法來代替Lambda表示式,列印:我喜歡喝茶....
Teacher t = new Teacher();
stu.playGame(t::like);//引用Teacher的like()方法。
//或者
stu.playGame(new Teacher()::like);
}
}
12、方法引用-使用super父類方法替代Lambda
@FunctionalInterface
interface Game{
public void run();
}
class Fu{
public void like(){
System.out.println("我喜歡喝啤酒(我是父親)....");
}
}
class Student extends Fu{
public void playGame(Game game) {
System.out.println("我開始打遊戲:");
game.run();
}
public void show(){
//1.使用Lambda
playGame(() -> System.out.println("我喜歡喝啤酒...."));
//2.使用父類的like方法代替Lambda表示式
playGame(super::like);//使用父類的like方法代替Lambda表示式
}
}
public class Demo {
public static void main(String[] args) {
Student stu = new Student();
stu.show();
}
}
13、方法引用-使用this本類方法替代Lambda
@FunctionalInterface
interface Game{
public void run();
}
class Student{
public void playGame(Game game) {
System.out.println("我開始打遊戲:");
game.run();
}
public void show(){
// playGame(() -> System.out.println("我喜歡打羽毛球...."));
playGame(this::ymq);
}
public void ymq(){
System.out.println("我喜歡打羽毛球....");
}
}
public class Demo {
public static void main(String[] args) {
Student stu = new Student();
stu.show();
}
}
14、方法引用-類的構造器引用
1)、無參的構造方法
class Cat{
public Cat(){
}
public void eat(){
System.out.println("小貓吃魚....");
}
}
interface CatFactory{
//生產Cat
public Cat getCat();
}
public class Demo {
public static void main(String[] args) {
//呼叫fun
//1.使用:匿名內部類
fun(new CatFactory() {
@Override
public Cat getCat() {
return new Cat();
}
});
//2.使用Lambda表示式
fun(()->{return new Cat();});
//3.使用Cat的無參構造方法替代:getCat()方法
fun(Cat::new);
}
public static void fun(CatFactory cf) {
Cat c = cf.getCat();
c.eat();
}
}
2)、有參構造方法
class Cat{
private String name;
public Cat(){
}
public Cat(String name) {
this.name = name;
}
public void eat(){
System.out.println("我是一隻 " + name + " 我愛吃魚....");
}
}
interface CatFactory{
//生產Cat
public Cat getCat(String name);
}
public class Demo {
public static void main(String[] args) {
//呼叫fun
//1.使用:匿名內部類
fun(new CatFactory() {
@Override
public Cat getCat(String name) {
return new Cat(name);
}
},"機器貓");
//2.使用Lambda表示式
fun((String n)->{return new Cat(n);},"機器貓");
//3.使用Cat的有參構造方法替代:getCat(String name)方法
fun(Cat::new,"機器貓");
}
public static void fun(CatFactory cf,String name) {
Cat c = cf.getCat(name);
c.eat();
}
}
15、方法引用-陣列構造器引用
@FunctionalInterface
interface IA{
public int[] getArr(int len);
}
public class Demo {
public static void main(String[] args) {
//2.使用Lambda
fun(