一、接口定义增强(新增默认方法和静态方法)
接口(Interface)在开发中广泛应用,如果接口设计不合理,那么接口的所有实现类都会受到影响。因此JDK1.8对接口做了优化,新增了默认方法和静态方法。
JDK1.8之前接口中的方法只有声明而没有方法体,具体方法在子类中实现。但如果某个方法是通用的,在所有实现类中的实现都是一样的,我们还有必要每个子类中都写一遍吗?当然没有必要!因此JDK1.8提供了默认方法,对于接口中的这种通用方法,可以在接口中直接写出方法体,子类无需实现就可通过对象调用。另外默认方法是支持重写的,子类可以根据具体需求更改默认方法。
interface IFunction{
default void print(){
System.out.println("我是通用的打印方法");
}
}
interface IFunction{
void print();
//静态方法
static IFunction getInstance(){
return new FunctionImpl();
}
}
class FunctionImpl implements IFunction{
@Override
public void print() {
System.out.println("test");
}
}
public class Demo{
public static void main(String[] args) {
//通过接口名调用
IFunction iFunction = IFunction.getInstance();
iFunction.print();
}
}
有没有发现此时的接口和抽象类非常相似?接口和抽象类到底有何异同(以JDK1.8为准):
相同点:
不同点:
二、lambda表达式
使用lambda表达式,可以简化代码,这是函数式编程的优点,而面向对象编程结构必须完整,下面通过对比来直观感受一下。
面向对象编程:
interface IFunction{
void print();
}
public class Demo implements IFunction{
@Override //实现接口方法
public void print() {
System.out.println("test");
}
public static void main(String[] args) {
IFunction Fc = new Demo();
Fc.print();
}
}
函数式编程:
@FunctionalInterface
interface IFunction{
void print();
}
public class Demo{
public static void main(String[] args) {
//使用lambda表达式,一行代码完成
IFunction Fc = () -> System.out.println("test");
Fc.print();
}
}
当然这只是举个简单例子,但是可以看到函数式编程明显代码简洁很多。那么lambda表达式是什么,怎么用呢?
Lambda表达式的语法:
(参数)-> {语句};
下面具体来看几种情况:
1、无参,无返回值
示例:Test t = () -> System.out.println("test");
2、一个参数
示例:Test t = (x) -> System.out.println(x);
(小括号也可以省略写成:Test t = x -> System.out.println(x); )
3、两个参数,并且有返回值
Test t = (x,y) -> {
System.out.println("test");
return x+y;
};
//当只有一条语句时,return和{}可以省略不写
Test t = (x,y) -> x+y;
4、类型推断:上面的示例中,都省略了Lambda 表达式中参数列表的数据类型。因为JVM编译器可通过上下文推断出数据类型。
三、方法引用
所谓方法引用,就是如果lambda表达式中的方法有现成的可以使用,那么就直接引用。因此方法引用可以看做是lambda表达式的另一种写法,其语法结构更加简单。方法引用的类型有四种:
我们来看下图的例子,Idea提示将lambda表达式替换为方法引用。
替换后结构更加简单:
@FunctionalInterface
interface IUtil{
R switchPara();
}
public class Test {
public static void main(String[] args) {
IUtil util = "hello"::toUpperCase;
String str = util.switchPara(); //转换的就是"hello"
System.out.println(str);
}
}
@FunctionalInterface
interface IUtil{
R compare(T t1,T t2);
}
public class Test {
public static void main(String[] args) {
//compareTo()为String类中的普通方法
IUtil util = String::compareTo;
int r = util.compare("111","222");
System.out.println(r);
}
}
class Student{
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
@FunctionalInterface
interface IUtil{
R createStudent(PN p1,PA p2);
}
public class Test {
public static void main(String[] args) {
IUtil util = Student::new; //引用构造方法
Student stu = util.createStudent("tony",18);
System.out.println(stu);
}
}
四、内建函数式接口
所谓函数式接口:就是接口中只有一个抽象方法,并且加上注解@FunctionalInterface。函数式接口是lambda表达式的核心。
函数式接口分以下四种(都是java自带的):
public interface Function {
R apply(T t);
}
public interface Supplier {
T get();
}
public interface Consumer {
void accept(T t);
}
public interface Predicate {
boolean test(T t);
}
来看具体例子:
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.function.Consumer;
import java.util.function.Predicate;
public class Demo{
public static void main(String[] args) {
Function func = Integer::parseInt;
//功能型:
Integer num =func.apply("123456");
System.out.println(num);
//供给型
Supplier supplier = "hello"::toUpperCase;
String str = supplier.get();
System.out.println(str);
//消费型
Consumer consumer = System.out::println;
consumer.accept("world");
//断言型
Predicate predicate = "**123**"::contains;
boolean effect = predicate.test("123");
System.out.println(effect);
}
}