一、接口定义增强
- 在接口中使用default或static定义普通方法,如下:
-
1 package com.mdln.com; 2 3 interface IMessage { 4 public void print();//接口中原本定义的抽象方法 5 6 default void fun() {//使用default定义的普通方法 7 System.out.println("新特性支持在接口中使用default定义方法"); 8 } 9 10 static void get() {//使用static定义的普通方法 11 System.out.println("新特性支持在接口中使用static定义方法"); 12 } 13 14 class MessageIpml implements IMessage { 15 public void print() { 16 System.out.println("覆写接口中的方法"); 17 } 18 } 19 20 public static void main(String[] args) { 21 IMessage im = new MessageIpml(); 22 im.print(); 23 im.fun(); 24 IMessage.get();//调用静态方法 25 } 26 }
二、Lamda表达式
解决匿名内部类代码繁杂而出现,那么
- 1、首先复习之前的匿名内部类
-
1 package com.mdln.com; 2 3 interface IMessage { 4 public void print(); 5 } 6 7 public class TestDemo { 8 public static void main(String[] args) { 9 fun(new IMessage() {// 匿名内部类 10 public void print() { 11 System.out.println("hello world"); 12 } 13 }); 14 } 15 16 public static void fun(IMessage msg) { 17 msg.print(); 18 } 19 }
- 2、使用Lamda表达式后的代码:
-
1 package com.mdln.com; 2 3 interface IMessage { 4 public void print(); 5 } 6 7 public class TestDemo { 8 public static void main(String[] args) { 9 fun(()->System.out.println("hello world")); 10 } 11 12 public static void fun(IMessage msg) { 13 msg.print(); 14 } 15 }
对于Lamda的形式有三种语法:
- (参数)->单行语句:
- (参数)->{多行语句}:
- (参数)->表达式:
1)带参数单行语句:
-
1 package com.mdln.com; 2 3 interface IMessage { 4 public void print(String str); 5 } 6 7 public class TestDemo { 8 public static void main(String[] args) { 9 //首先定义出此表达式接受的内容,单行语句直接进行输出 10 fun((s)->System.out.println(s)); 11 } 12 13 public static void fun(IMessage msg) { 14 //设置参数内容 15 msg.print("hello world"); 16 } 17 }
2)多行语句
-
1 package com.mdln.com; 2 3 interface IMessage { 4 public void print(String str); 5 } 6 7 public class TestDemo { 8 public static void main(String[] args) { 9 // 首先定义出此表达式接受的内容,单行语句直接进行输出 10 fun((s) -> { 11 s = s.toUpperCase(); 12 System.out.println(s); 13 }); 14 } 15 16 public static void fun(IMessage msg) { 17 // 设置参数内容 18 msg.print("hello world"); 19 } 20 }
3)代码中只是一个简单的表达式
-
1 package com.mdln.com; 2 3 interface IMessage { 4 public int add(int x, int y); 5 } 6 7 public class TestDemo { 8 public static void main(String[] args) { 9 fun((s1, s2) -> s1 + s2); 10 } 11 12 public static void fun(IMessage msg) { 13 System.out.println(msg.add(10, 20)); 14 } 15 }
三、方法引用:为方法设置一个别名,相当于一个方法定义了不同的名字
JAVA8定义了如下四种形式的引用方法:
1)引用静态方法:类名称::static方法名称;
2)引用某个对象的方法:实例化对象::普通方法
3)引用特定类型的方法:特定类::普通方法
4)引用构造方法:类名称::new。
- 引用静态方法举例:在String的方法里有一个valueOf()方法:public static String valueOf(int x)
-
1 package com.mdln.com; 2 /** 3 * 实现方法的引用接口 4 * @param <P>引用方法的参数类型 5 * @param <R>引用方法的返回类型 6 */ 7 interface IMessage<P, R> { 8 public R zhuanhuan(P p); 9 } 10 public class TestDemo { 11 public static void main(String[] args) { 12 // 将String.valueOf()方法变为了IMessage接口里的zhuanhuan()方法 13 IMessage<Integer, String> msg = String::valueOf; 14 String str = msg.zhuanhuan(1000); 15 System.out.println(str.replaceAll("0", "9")); 16 } 17 }
- 普通方法引用
-
1 package com.mdln.com; 2 /** 3 * 实现方法的引用接口 4 * @param <P>引用方法的参数类型 5 * @param <R>引用方法的返回类型 6 */ 7 interface IMessage<R> { 8 public R upper(); 9 } 10 public class TestDemo { 11 public static void main(String[] args) { 12 // String类的toUpperCase()方法定义:public String toUpperCase() 13 //这个方法没有参数,但是有返回值,而且此方法一定要在有实例化对象的时候才可以调用 14 //"hello"字符串是String类的实例化对象,所以可以直接调用toUpperCase()方法 15 //将toUpperCase()函数的应用交给了IMessage接口 16 IMessage<String> msg = "hello"::toUpperCase; 17 String str = msg.upper();//相当于"hello".toUpperCase() 18 System.out.println(str); 19 } 20 }
如果要实现函数的引用,那么必须要有接口,而且接口里必须只存在一个方法,如果在多一个方法,方法无法进行引用。为了保证接口里只有一个方法,加入注解@FunctionalInterface声明,表示函数式接口
-
1 /** 2 * 实现方法的引用接口 3 * @param <P>引用方法的参数类型 4 * @param <R>引用方法的返回类型 5 */ 6 @FunctionalInterface//此为函数式接口,只能定义一个方法 7 interface IMessage<R> { 8 public R upper(); 9 }
- 引用特定类型的方法
-
通常,如果使用“类::方法”引用的一定是类中的静态方法,但是这种形式也可以引用普通方法,String类中有一个方法public int compareTo(String anotherString)
-
1 package com.mdln.com; 2 3 /** 4 * 实现方法的引用接口 5 * @param <P>引用方法的参数类型 6 * @param <R>引用方法的返回类型 7 */ 8 @FunctionalInterface // 此为函数式接口,只能定义一个方法 9 interface IMessage<P> { 10 public int compare(P p1, P p2);//理解为前面调用对象,后面传入参数 11 //public int compareTo(String anotherString),比较形式:字符串1对象.compareTo(字符串2对象),要准备出两个参数 12 } 13 14 public class TestDemo { 15 public static void main(String[] args) { 16 IMessage<String> msg = String::compareTo; 17 System.out.println(msg.compare("A", "B")); 18 } 19 }
与之前相比,方法引用前,不需要再定义对象,而可以理解为将对象定义在了参数上
-
引用构造方法
-
1 package com.mdln.com; 2 /** 3 * 实现方法的引用接口 4 * @param <P>引用方法的参数类型 5 * @param <R>引用方法的返回类型 6 */ 7 @FunctionalInterface // 此为函数式接口,只能定义一个方法 8 interface IMessage<C> { 9 public C create(String t, double p);// 理解为前面调用对象,后面传入参数 10 // public int compareTo(String 11 // anotherString),比较形式:字符串1对象.compareTo(字符串2对象),要准备出两个参数 12 } 13 class Book { 14 private String title; 15 private double price; 16 17 public Book(String title, double price) { 18 this.title = title; 19 this.price = price; 20 } 21 public String toString() { 22 return "书名" + this.title + ",价格:" + this.price; 23 } 24 } 25 public class TestDemo { 26 public static void main(String[] args) { 27 IMessage<Book> msg = Book::new;// 引用构造 28 Book book = msg.create("JAVA开发", 9.0);//虽然调用的是create()方法,其实是引用Book类里的构造 29 System.out.println(book); 30 } 31 }
四、内建函数式接口
JDK1.8中的java.util.function包中提供了四个函数式接口,分别如下:
- 功能性接口(Function): public interface Function<T,R>{public R apply(T t)}:此接口需要接受一个参数,返回一个处理结果
- 消费性接口(Consumer):public interface Consumer<T>{public void accept(T t)}:只负责接受数据,并不返回处理结果
- 供给型接口(Supplier): public interface Supplier<T> {public T get()}:此接口不接收参数,但返回结果
- 断言型接口(Predicate):public interface Predicate<T>{public boolean test(T t)}:进行判断操作使用
- 举例1:功能性接口:String有一个方法:public Boolean startsWith(String str)
1 package com.mdln.com; 2 3 import java.util.function.Function; 4 5 public class TestDemo { 6 public static void main(String[] args) { 7 Function<String, Boolean> fun = "##hello"::startsWith; 8 System.out.println(fun.apply("##")); 9 } 10 }
- 消费型接口:自定义了一个
1 package com.mdln.com; 2 3 import java.util.function.Consumer; 4 5 class MyDemo { 6 public void print(String str) {// 此方法只能接收,不能返回 7 System.out.println(str); 8 } 9 } 10 11 public class TestDemo { 12 public static void main(String[] args) { 13 Consumer<String> cons = new MyDemo()::print; 14 cons.accept("hello"); 15 } 16 }
- 供给型接口:String类中的一个方法:public String toUpperCase()
1 package com.mdln.com; 2 3 import java.util.function.Supplier; 4 5 public class TestDemo { 6 public static void main(String[] args) { 7 Supplier<String> sup = "hello"::toUpperCase; 8 System.out.println(sup.get()); 9 } 10 }
- 断言型接口:String类中的一个方法:
1 package com.mdln.com; 2 3 import java.util.function.Predicate; 4 5 public class TestDemo { 6 public static void main(String[] args) { 7 Predicate<String> pre = "hello"::equalsIgnoreCase; 8 System.out.println(pre.test("hello")); 9 } 10 }