JDK1.8常用新特性

一、接口定义增强(新增默认方法和静态方法)

接口(Interface)在开发中广泛应用,如果接口设计不合理,那么接口的所有实现类都会受到影响。因此JDK1.8对接口做了优化,新增了默认方法和静态方法。

  • 默认方法:使用default定义,通过对象调用

JDK1.8之前接口中的方法只有声明而没有方法体,具体方法在子类中实现。但如果某个方法是通用的,在所有实现类中的实现都是一样的,我们还有必要每个子类中都写一遍吗?当然没有必要!因此JDK1.8提供了默认方法,对于接口中的这种通用方法,可以在接口中直接写出方法体,子类无需实现就可通过对象调用。另外默认方法是支持重写的,子类可以根据具体需求更改默认方法。

interface IFunction{
    default void print(){
        System.out.println("我是通用的打印方法");
    }
}
  • 静态方法:使用static定义,通过接口名调用
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为准):

相同点:

  • 二者都是抽象类型;
  • 都可以有具体的实现方法;
  • 所有方法的实现不是必须的。

不同点:

  • 抽象类不可以多继承,而接口可以;
  • 设计理念不同。抽象类表示的是"is-a"关系,接口表示的是"like-a"关系;
  • 接口中定义的变量默认是public static final,必须初始化且之后不能改变;而抽象类中的变量是default,可以在子类中重新定义和赋值。

二、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表达式的底层实现是匿名内部类。
  • 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表达式的另一种写法,其语法结构更加简单。方法引用的类型有四种:

  • 引用静态方法:类名称 :: static 方法名称 ;

我们来看下图的例子,Idea提示将lambda表达式替换为方法引用。

JDK1.8常用新特性_第1张图片

替换后结构更加简单:

JDK1.8常用新特性_第2张图片

  • 引用某个对象的方法:实例化对象 :: 普通方法 ;
@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);
      }
  }
  • 引用构造方法:类名称 :: new ;
 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);
}
  • 断言型函数式接口:有参有返回,返回lboolean类型
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);
    }
}

 

你可能感兴趣的:(java知识点)