java8新特性

github地址: https://github.com/lishanglei/java8-character

1.接口的静态方法和默认方法

java8之前,接口只允许存在抽象方法,即默认被public abstract修饰
java8新增静态方法和默认方法
1.1静态方法

1.接口中允许存在被static修饰的方法且该方法必须有方法体

2.接口中的static方法只能够被接口本身调用: 接口名.静态方法名(…)

3.接口的static方法不能被子接口继承

4.接口的static方法不能给被实现类重写及直接调用

public interface MyInterface {

//接口中的方法默认使用public abstract修饰
public abstract void test();

//java8中允许接口中存在静态方法,该静态方法必须包含方法体
static void staticMethod(){
    System.out.println("hello java8  static method  ...");
};
}
1.2默认方法

default关键词修饰的方法是对该抽象方法一种默认的实现,可以被继承类或者实现类重写

public interface MyInterface {
    
        default void defaultMethod() {
            System.out.println("hello java8 default method ...");
        }
    }

2.函数式接口(Functional Interface)

就是有且仅有一个抽象方法,但是可以有多个非抽象方法的接口,函数式接口可以被隐式转换为lambda表达式

@FunctionalInterface
public interface FunctionInterface {

    void test();
    /**
     * 当接口中有且只有一个抽象方法时,
     * 可以在接口上添加@FunctionalInterface注解
     */
    //void test3();

    static void test1(){};

    default void test2(){};
}

JDK1.8之前已有的函数式接口

java.lang.Runnable   
java.util.concurrent.Callable
java.security.PrivilegedAction
java.util.Comparator
java.io.FileFilter
java.nio.PathMatcher
java.lang.reflect.InvocationHandler
java.beans.PropertyChangeListener
java.awt.event.ActionListener
javax.swing.event.ChangeListener

JDK1.8新增的函数接口

java.util.Function

3.lambda表达式

Lambda表达式可以看成是对匿名内部类的简写,使用Lambda表达式时,接口必须是函数式接口

lambda表达式的作用域:
  • 在lambda表达式中访问外层作用域和老版本的匿名对象中的方式相似,
  • 可以直接访问标记了final的外部局部变量,或者实例的字段及静态变量,但如果访问局部变量
    public class MyTest {
    //实例变量
    int score =20;
    //静态变量
    static int salary=10000;
    public static void main(String[] args) {
//局部变量
     int age =9;

     /**实现类*/
     MyInterface myInterface =new MyInterfaceImpl();
     System.out.println(myInterface.sum(2,3));

     /**匿名内部类*/
     MyInterface myInterface1 =new MyInterface() {

         public int sum(int num1, int num2) {
             return num1+num2;
         }
     };
     System.out.println(
           myInterface1.sum(3,5)
     );

     /**lambda表达式*/
     MyInterface myInterface2 =(int num1,int num2)->{
         /**
          * 访问局部变量,则该局部变量则默认被final修饰,不能改变值
          */
         //age=10;
         System.out.println(age);
         System.out.println(new MyTest().score);
         System.out.println(salary);
         return num1+num2;
     };

     System.out.println(myInterface2.sum(8,9));
     /**
      * lambda表达式简写
      * 1.形参类型可以省略
      * 2.如果方法体中只有一句,可以省略{}
      * 3.如果是return返回结果的,可以省略掉return
      * 4.如果只有一个参数,()也可以省略
      */
     //MyInterface myInterface3 =(num1,num2)->num1+num2;

 }

}

4.构造方法引用 / 静态方法引用 / 实例方法引用

4.1构造方法引用
public class ConstructorTest {

    public static void main(String[] args) {

        /**
         * 1.匿名内部类
         */
        PersonFactory factory = new PersonFactory() {
            public Person createPerson(String firstName, String secondName) {
                return new Person(firstName, secondName);
            }
        };

        Person person = factory.createPerson("hello", "world");
        System.out.println(person);

        /**
         * 2.使用lambda表达式
         */
        PersonFactory factory1 = (firstName, secondName) -> new Person(firstName, secondName);

        System.out.println(factory1.createPerson("zhagnsan","lisi"));

        /**
         * 3.lambda表达式简单写法:构造方法引用
         */
        PersonFactory factory2 =Person::new;
        System.out.println(factory2.createPerson("盖伦","诺克"));
    }
}
4.2静态方法引用
public class StaticTest {

    public static void main(String[] args) {

        //1.匿名内部类
        ParseInterface parseInterface =new ParseInterface() {
            @Override
            public int parseString(String str) {
                return Integer.parseInt(str);
            }
        };
        System.out.println(parseInterface.parseString("3"));

        //2.lambda表达式写法
        ParseInterface parseInterface1 =(str)->Integer.parseInt(str);
        System.out.println(parseInterface1.parseString("5"));

        //3.静态方法引用
        ParseInterface parseInterface2 =Integer::parseInt;
        System.out.println(parseInterface2.parseString("7"));
    }
}
4.3实例方法引用
public class InstanceTest {

    public static void main(String[] args) {

        /**
         * 1.使用匿名内部类
         */
        Function function =new Function<String,Boolean>() {
            @Override
            public Boolean apply(String s) {
                return s.endsWith("java");
            }
        };
        System.out.println(function.apply("hello.java"));

        /**
         * 使用匿名内部类
         */
        Function<String,Boolean> function1 =(s)->s.endsWith(s);
        System.out.println(function1.apply("你好.java"));

        /**
         * 实例方法引用
         */
        Function<String,Boolean> function2 ="world.java"::endsWith;
        System.out.println(function2.apply("java"));
    }
}

5.Predicate函数式接口

接收一个泛型,返回一个boolean类型的结果

源码
@FunctionalInterface
public interface Predicate<T> {
     boolean test(T t);
}
演示
public class PredicateTest {

    public static void main(String[] args) {
        Predicate<Integer> predicate = age -> age > 10;
        System.out.println(predicate.test(17));

        Predicate<Integer> predicate1=age->age<30;
        Predicate<Integer> predicate2 = predicate.and(predicate1);
        System.out.println(predicate2.test(8));
    }
}

6.Consumer函数式接口

接收一个泛型,没有返回类型

源码
@FunctionalInterface
public interface Consumer<T> {
    void accept(T t);
}
演示
public class ConsumerTest {
    public static void main(String[] args) {

        Consumer<String> consumer =out::print;
        consumer.accept("abc");
    }
}

7.Supplier

接收一个泛型,返回该泛型

源码
@FunctionalInterface
public interface Supplier<T> {

    T get();
}
演示
public class supplier {

    public static void main(String[] args) {
//        Supplier<String> supplier = () -> "这是返回的字符串对象";
//        System.out.println(supplier.get());

        Supplier<Student> studentSupplier = Student::new;
        System.out.println(studentSupplier.get());
    }
    
    static class Student {
        private String name;
        private Integer age;

        public Student(String name, Integer age) {
            this.name = name;
            this.age = age;
        }

        public Student() {
            this.name = "name";
            this.age = 18;
        }

        @Override
        public String toString() {
            return "Student{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }
}