jdk新特性(一)接口和lambda表达式

引言

  • 伴随着编程技术的不断发展,oracle为了编程的便捷和提升项目的可维护性,对java做了许多的升级,比如新出现的lambda表达式的引入,在接口中增加静态方法和默认方法以及提取私有方法,下文首先复习一下lambda表达式。

lambda表达式

为什么采用lambda表达式?

  • Lambda表达式是为了使得接口编程更加方便,这也可以与从lambda表达式的编程思想来考虑,函数式思想则尽量忽略面向对象的复杂语法:“强调做什么,而不是以什么形式去做”,所以这个可以使java编程变得更加优雅,代码更加简洁。

使用Lambda表达式需要注意的事项有哪些?

  1. 使用Lambda必须要有接口,并且要求接口中有且仅有一个抽象方法。
  2. 必须有上下文环境,才能推导出Lambda对应的接口。
    以下是lambda表达式的具体实例理解。
    根据局部变量的赋值得知Lambda对应的接口
    Runnable r = () -> System.out.println(“Lambda表达式”);
    根据调用方法的参数得知Lambda对应的接口
    new Thread(() -> System.out.println(“Lambda表达式”)).start();
    可以将lambda表达式理解为实现接口的一个对象()

lambda表达式与匿名内部类有什么区别?

1)所需类型不同
匿名内部类:可以是接口,也可以是抽象类,还可以是具体类
Lambda表达式:只能是接口

2)使用限制不同
如果接口中有且仅有一个抽象方法,可以使用Lambda表达式,也可以使用匿名内部类,如果接口中多于一个抽象方法,只能使用匿名内部类,而不能使用Lambda表达式。
3)实现原理不同
匿名内部类:编译之后,产生一个单独的.class字节码文件
Lambda表达式:编译之后,没有一个单独的.class字节码文件。对应的字节码会在运行的时候动态生成。

案例

采用lambda表达式和匿名内部类实现绵绵的接口,并体会两种方式的不同。
接口类1

public interface Addable {
    int add(int x, int y);
}

接口类2

public interface Eatable {
    void eatable(String s);
}

接口类3

public interface Likable {
    void like(String s);
}

测试类

public class LambdaDemo {
    public static void main(String[] args) {

        useAddable(new Addable() {
            @Override
            public int add(int x, int y) {
                System.out.println("------------Add采用匿名内部类-------------");
                return x+y;
            }
        });

        useEatable(new Eatable() {
            @Override
            public void eatable(String s) {
                System.out.println("----------Eat采用匿名内部类------------");
                System.out.println(s);
            }
        });

        useLikable(new Likable() {
            @Override
            public void like(String s) {
                System.out.println(s);
            }
        });

        System.out.println("----------采用lambda表达式--------------");

        useAddable((int x,int y)->{
            System.out.println("-------------Eat采用lambda表达式---------------");
            return x+y;
        });

        useEatable((String str)->{
            System.out.println("----------Eat采用lambda表达式------------");
        });
        useLikable((String s)->{
            System.out.println(s);
        });

        System.out.println("----------采用省略lambda表达式----------");
        useEatable((s)-> System.out.println(s));

        useAddable((x,y)->x+y);

        useLikable((s)-> System.out.println(s));
    }

    public static void useEatable(Eatable eat){
        eat.eatable("我爱吃苹果");
    }

    public static void useAddable(Addable add){
        int sum = add.add(10, 20);
        System.out.println("sum:"+sum);
    }

    public static void useLikable(Likable like){

        //System.out.println("--------i love java---------");
        //System.out.println("---------i love python----------");
        like.like("--------i love java---------");
        like.like("---------i love python----------");
    }

}

测试结果
在这里插入图片描述

接口新特性

  • Jdk根据用户需求在接口中可以加入静态方法,默认方法,私有方法等等,这都是为了方便项目扩展,减少代码之间的耦合性,下面来看实际案例。

案例

体验jdk中新增带有方法体的私有方法。
接口类

public interface MyInterface {

    void show(String s);

    public static void show01(){
        System.out.println("---------this is static void show01----------");
        show03();
        //无法调用非静态方法
        //show04();
    }

    public default void show02(){
        System.out.println("-----------this is default void show03------------");
        show03();
        show04();
    }

    private static void show03(){
        System.out.println("---------this is private static void show03--------");
    }

    private void show04(){
        System.out.println("---------this is private normal void show04--------");
    }
}

测试类

public class TestDemo {
    public static void main(String[] args) {
        useMyInterface((s)->{
            System.out.println("------这是通过lambda表达式实现MyInterface的show方法-------");
            System.out.println(s);
        });
        MyInterface.show01();


        MyInterface myInterface = new MyInterface() {
            @Override
            public void show(String s) {
                System.out.println("------这是通过new的对象实现MyInterface的show方法-------");
                System.out.println(s);
            }
        };
        myInterface.show("I LOVE PYTHON");
        myInterface.show02();
    }

    public static void useMyInterface(MyInterface myInterface){
        myInterface.show("i love java");
    }
}

测试结果
在这里插入图片描述

notes

默认方法可以调用私有的静态方法和非静态方法
静态方法只能调用私有的静态方法。

方法引用

为什么会出现方法引用?

在使用Lambda表达式的时候,我们实际上传递进去的代码就是一种解决方案:拿参数做操作那么考虑一种情况:如果我们在Lambda中所指定的操作方案,已经有地方存在相同方案,所以就再也没有必要写重复逻辑。

什么是方法引用符?

:: 该符号为引用运算符,而它所在的表达式被称为方法引用

lambda表达式和方法引用是什么关系?

方法引用是Lambda的孪生兄弟
如果使用Lambda,那么根据“可推导就是可省略”的原则,无需指定参数类型,也无需指定的重载形式,它们都将被自动推导;如果使用方法引用,也是同样可以根据上下文进行推导。

案例一

各类接口

public interface Converter {
    int convert(String s);
}
public interface MyString {
    String mySubString(String str,int x, int y);
}

public interface Printable {
    void printUpperCase(String s);
}

    Student build(String name,int age);
}

学生类

public class Student {
    private String name;
    private int age;
    public Student() {
    }
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

printStr类

public class PrintStr {
    public void printUpper(String s){
        String str = s.toUpperCase();
        System.out.println(str);
    }
}

测试类

public class ReferenceDemo {
    public static void main(String[] args) {
       useConverter((s)->{
            int i = Integer.parseInt(s);
            //System.out.println(i);
            return i;
        });
        //采用静态方法
        useConverter(Integer::parseInt);
        System.out.println("-----------------------");
        //采用lambda接口来
        usePrintStr((s)->{
            System.out.println(s.toUpperCase());
        });
        //采用对象应用方法
        PrintStr printStr = new PrintStr();
        usePrintStr(printStr::printUpper);
        System.out.println("-----------------------");
        //引用类中成员方法
        useMyString((s,x,y)-> s.substring(x,y));
        useMyString(String::substring);
        System.out.println("------------------------");
        //采用构造方法
        useStudentBuilder((s,x)->new Student(s,x));
        useStudentBuilder(Student::new);
    }
    public static void useConverter(Converter converter){
        System.out.println("the result is:"+converter.convert("666"));
    }
    public static void usePrintStr(Printable printable){
        printable.printUpperCase("I Love Java I Love Python");
    }
    public static void useMyString(MyString myString){
        String str = myString.mySubString("HelloJava", 1, 6);
        System.out.println(str);
    }
    public static void useStudentBuilder(StudentBuilder studentBuilder){
        Student student = studentBuilder.build("赵丽颖", 34);
        System.out.println(student.getName()+":"+student.getAge());
    }
}

测试结果
在这里插入图片描述

案例二

采用

public class FunctionInterface {
    public static void main(String[] args) {
        String string = getString(() -> "巨量鹏");
        System.out.println(string);
        System.out.println("-------------------");

        int val = getInteger(() -> 30);
        System.out.println(val);

        System.out.println("------------------");
       int[] arr = {19, 97, 28, 37, 46,76};

        int maxVal=getMax(()->{
            int max =arr[0];
            for (int i = 1; i < arr.length; i++) {
                if(arr[i]>max){
                    max=arr[i];
                }
            }
            return max;
        });
        System.out.println(maxVal);
        System.out.println("------------------");
        /*operatorString("天量鹏",(String s)->{
            System.out.println(s);
        });*/
        //采用lambda表达式
        operatorString("天量鹏", s-> System.out.println(s));
        //采用函数式应用
       // operatorString("天量鹏",  System.out::println);
        //采用匿名内部类
        operatorString("若皮赞", new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        });
        //反向输入
        operatorString("天量鹏",s-> System.out.println(new StringBuilder(s).reverse().toString()));
        System.out.println("---------------------------");
        operatorString("天量鹏",s-> System.out.println(s),
                s-> System.out.println(new StringBuilder(s).reverse().toString()));
        System.out.println("---------------------------");
        String [] strArr={"杨颖,38","赵丽颖,34"};
        operatorString(strArr,s -> {
            String sName=s.split(",")[0];
            System.out.println("姓名:"+sName);
        },s->{
            int sAge=Integer.parseInt(s.split(",")[1]);
            System.out.println("年龄:"+sAge);
        });
        System.out.println("------------------------");
        boolean test = checkString("hello", s ->
                        s.length() > 4
                ,s -> s.length() < 9);
        System.out.println(test);
        System.out.println("------------------------");
        String [] str= {"刘亦菲,40","刘岩,42","韩雪,44","文章,32","迪丽热巴,36","杨幂,37","我爱罗,34"};
        ArrayList<String> arrayList = condition(str, s -> {
            String s1 = s.split(",")[0];
            return s1.length() > 2;
        }, s -> {
            int i = Integer.parseInt(s.split(",")[1]);
            return i > 35;
        });
        for (String o : arrayList) {
            System.out.println(o);
        }
        System.out.println("--------------------------");
        String myConverter = converter("120", 6, (s) -> {
            return Integer.parseInt(s);
        }, (s) -> Integer.toString(s));
        System.out.println(myConverter);

    }
    //定义一个方法,返回一个整数数据
    private static Integer getInteger(Supplier<Integer> sup) {
        return sup.get();
    }
    //定义一个方法,返回一个字符串数据
    private static String getString(Supplier<String> sup) {
        return sup.get();
    }
    private static int getMax(Supplier<Integer> sup){
        return sup.get();
    }
    private static void operatorString(String str, Consumer<String> consumer){
        consumer.accept(str);
    }
    private static void operatorString(String str, Consumer<String> consumer1,Consumer<String > consumer2){
        //consumer1.accept(str);
        //consumer2.accept(str);
        consumer1.andThen(consumer2).accept(str);
    }
    private static void operatorString(String [] str,Consumer<String> consumer1,Consumer<String > consumer2){
        for (String s :
                str) {
            consumer1.andThen(consumer2).accept(s);
        }
    }
    private static boolean checkString(String s, Predicate<String> s1,Predicate <String> s2){
        /*boolean test1 = s1.test(s);
        boolean test2=s2.test(s);
        return test1&&test2;*/
        //也可以使用or方法
        return s1.and(s2).test(s);
    }
    private static ArrayList condition(String [] str,Predicate<String> s1,Predicate<String> s2){
        ArrayList<String> arrayList = new ArrayList<>();
        for (String s : str) {
            boolean test = s1.and(s2).test(s);
            if(test){
                arrayList.add(s);
            }
        }
        return arrayList;
    }
    //Function接口
    private  static String converter(String s, int startVal, Function<String ,Integer > fun1,Function<Integer ,String > fun2){
        Integer apply = fun1.apply(s)+startVal;
        String apply1 = fun2.apply(apply);
        return apply1;
        //不能满足要求
        //return  fun1.andThen(fun2).apply(s);
    }
}

测试结果
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/xueshanfeitian/article/details/108972773