Java 8 简单使用,Android工程师面试题及答案

本文介绍了Java 8中的Lambda表达式及其四种样式,并讲解了它们在函数式接口上的应用。文章还探讨了Java 8新增的Predicate、Consumer、Function和Supplier等函数式接口。此外,方法引用的概念被提出,包括如何使用方法引用创建Lambda表达式。文章结合设计模式的学习,展示了如何在实际开发中减少重复代码,提高代码复用性。
摘要由CSDN通过智能技术生成
         Log.d("I","exe");
    }
}); 
```

> 匿名内部类/监听器接口缺点在于代码很臃肿,而lambda表达式就是对其进行了简化.

```
func(()->Log.d("I","exe")); 
```

> Lambda表达式并不能让你实现以前不能实现的功能
2. Lambda表达式的几种样式
  1. 总体样式: (参数列表) -> {代码块; return **;}```
    (参数列表) -> 单行代码

    (参数列表) -> {代码;}

    (参数列表) -> {
    代码;
    return 返回值;
    }

    (参数列表) -> {return 返回值;}

    (参数列表) -> 返回值

    
    
3. Lambda表达式可以用在哪里: 在函数式接口上使用.
  1. 什么是函数式接口: 函数式接口就是仅有1个抽象方法的接口

    • 注意只针对抽象方法数量进行限制.
    • 一个接口即使包含很多默认/default方法,只有接口中只定义了1个抽象方法,依然是函数式接口.
    • DefaultInterface虽然有很多默认方法,但仅包含1个抽象方法,也属于函数式接口.
    @FunctionalInterface
    public interface DefaultInterface {
        void f1();
        default void f2(){};
        default void f3(){};
        default void f4(){};
    } 
    
    • 对于函数式接口,建议添加注解@FunctionalInterface ,但不是必须的.
  2. Lambda表达式允许直接以内联的形式为函数式接口的抽象方法提供实现,并将整个Lambda表达式作为该函数式接口的1个实例.

    • 由此可见,传递指定接口实例,使用匿名内部类,和使用Lambda表达式本质是一样的,都是传递1个"实例".
    • Lambda表达式只是让代码更简洁.
  3. 函数式接口的抽象方法的签名基本上就上Lambda表达式的签名.

    • 根据这个规则,对照函数式接口的’方法形式’,就可以写出对应的Lambda表达式
    • (type p1,type p2, ***) -> { 方法体; }
    @FunctionalInterface
    public interface FuncI1{
        void f();
    }
    @FunctionalInterface
    public interface FuncI2{
        void f1(int p1,int p2);
    }
    
    private void testLambdaFuncSign() {
        //以Runnable为例
        //Runnable就属于函数式接口
        //@FunctionalInterface
        //public interface Runnable {
        Runnable r1 = new Runnable() {
            @Override
            public void run() {
            }
        };
        Runnable r2 = () -> {
        };
    
        //以自定义函数式接口为例
        FuncI1 funcI11 = new FuncI1() {
            @Override
            public void f() {
            }
        };
        FuncI1 funcI12 = () -> {};
        FuncI2 funcI21 = new FuncI2() {
            @Override
            public void f1(int p1, int p2) {
            }
        };
        FuncI2 funcI22 = (p1, p2) -> {};
    } 
    
4. Java8新增的函数式接口
  1. Predicate

    • Predicate接收泛型T实例,返回boolean值. T->boolean.
    • Predicate常用于对流中的数据进行过滤,及其他根据1个实例返回boolean的场景
    • 示例
    @FunctionalInterface
    public interface Predicate<T> {
        boolean test(T t);
    }
    
    public class Person{
        public String name = "Li Lei";
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
    }
    @RequiresApi(api = Build.VERSION_CODES.N)
    public boolean testPerson(Person person, Predicate<Person> predicate){
        return predicate.test(person);
    }
    @RequiresApi(api = Build.VERSION_CODES.N)
    public void testPredicate(){
        Predicate<Person> personPredicate = person -> person.getName().equals("Han Meimei");
        testPerson(new Person(),personPredicate);
    } 
    
  2. Consumer

    • Consumer接收一个泛型T实例,无返回. T->void
    • 从命名即可看出,单纯消费一个实例.
    • 示例
    @FunctionalInterface
    public interface Consumer<T> {
        //单纯地消费1个实例
        void accept(T t);
    }
    
    @RequiresApi(api = Build.VERSION_CODES.N)
    public void testConsumer(){
        List<String> list = Arrays.asList("1","2","3");
        Consumer<String> consumer = s -> Log.d("TestConsumer","当前项:" + s);
        list.forEach(consumer);
    } 
    
  3. Function

    • Function接收1个泛型T实例,返回1个泛型R实例. T->R
    • 可以理解为常规的 输入->输出.
    • 示例
    @FunctionalInterface
    public interface Function<T, R> {
        //接收T实例,返回R实例
        R apply(T t);
    }
    
    @RequiresApi(api = Build.VERSION_CODES.N)
    public void testFunction(){
        /*
        Function<String, Integer> function = new Function<String, Integer>() {
            @Override
            public Integer apply(String s) {
                return Integer.parseInt(s);
            }
        };
        */
        //这里再次复习一下使用Lambda表达式表示 函数式接口实例
        Function<String, Integer> function = s -> Integer.parseInt(s);
        int result = function.apply("1000");
    } 
    
  4. Supplier

    • Supplier不接收实例,直接生成一个泛型T实例. void->T
    • 从名字就可以看出,是一个生产者
    • 示例
    @FunctionalInterface
    public interface Supplier<T> {
        T get();
    }
    @RequiresApi(api = Build.VERSION_CODES.N)
    public void testSupplier() {
        Supplier<Person> supplier = () -> new Person();
        Person person = supplier.get();
    } 
    
5. 方法引用
  1. 方法引用就是让你根据已有的方法来创建Lambda表达式.

  2. 方法引用的格式: 目标引用::方法名称

  3. 方法引用主要有3类

    • 指向静态方法 的 方法引用
      • 表现形式: className::func
    • 指向任意类实例指定方法 的 方法引用
      • 表现形式: className::func
    • 指向现有实例的指定方法 的 方法引用
      • 表现形式: instance::func
    public class PersonOpt{
        private String gainTag(Person person){
            return "Tag" + person.getName();
        }
    }
    @RequiresApi(api = Build.VERSION_CODES.N)
    public void testMethodReference() {
        //指向静态方法 的 方法引用
        //这里指向的是Integer类的静态方法
        //本质: className.func(param)
        //形式: className::func
        Function<String,Integer> f1 = (s) -> Integer.parseInt(s);
        Function<String,Integer> f2 = Integer::parseInt;
    
        //指向任意类实例指定方法 的 方法引用
        //这里指向的就是Person类中的非静态方法 getName
        //本质: param.func()
        //形式: className::func
        Function<Person,String> f3 = (p) -> p.getName();
        Function<Person,String> f4 = Person::getName;
    
        //指向现有实例的指定方法 的 方法引用
        //这里指向的是PersonOpt实例的非静态方法personOpt
        //本质: instance.func(param)
        //形式: instance::func
        PersonOpt personOpt = new PersonOpt();
        Function<Person,String> f5 = new Function<Person, String>() {
            @Override
            public String apply(Person person) {
                return personOpt.gainTag(person);
            }
        };
        Function<Person,String> f6 = personOpt::gainTag;
    } 
    
  4. 对构造函数的引用: ClassName::new

    • 构造函数引用适合用于生产者/Supplier
    • 构造函数的形式就是 void->T
    @RequiresApi(api = Build.VERSION_CODES.N)
    public void testConstructorRef(){
        Supplier<Person> supplier1 = new Supplier<Person>() {
            @Override
            public Person get() {
                return new Person();
            }
        };
        Supplier<Person> supplier2 = () -> new Person();
        //public Person(){} 构造函数的形式就是 void -> T
        Supplier<Person> supplier3 = Person::new;
    } 
    
  5. Lambda表达式和方法引用怎么用

    这里以1个自定义的需求为例.

    我们使用的很多方法都是参数传入,结果返回.

    比如输入3个参数,返回1个结果.

    同样形式的方法有很多个:

    public String f1(int p1,long p2, double p3){
        return **;
    }
    public int f2(int p1,String p2,Person p3){
        return **;
    }
    public Person f3(int p1,long p2,Dog dog){
        return **;
    } 
    

    使用lambda表达式及函数引用,可以实现’形式上的复用’.降低代码量.

    • 首先根据入参和返回结果的形式,创建对应的函数式接口.比如3个入参,返回1个结果,可以定义1个包含4个泛型数据的函数式接口.
    • 然后使用Lambda表达式创建该函数式接口的对应实例即可.避免声明过多方法.
    //1:构造1个函数式接口/只有1个抽象方法的接口
    @FunctionalInterface
    public interface CustomInterface<Source,Param1,Param2,Result>{
        Result gainResult(Source source,Param1 param1,Param2 param2);
    }
    //2:创建该函数式接口的实例
    public void testCustomInterface(){
        //原始形式创建
        CustomInterface<String,Integer,Integer,String> c1 = new CustomInterface<String, Integer, Integer, String>() {
            @Override
            public String gainResult(String s, Integer param1, Integer param2) {
                return s.substring(param1,param2);
            }
        };
        //lambda表达式创建
        //(参数列表) -> {return result;}
        CustomInterface<String,Integer,Integer,String> c2 = (source,param1,param2) -> {return source.substring(param1,param2);};
        //(参数列表) -> result
        CustomInterface<String,Integer,Integer,String> c3 = (source,param1,param2) -> source.substring(param1,param2);
        //直接使用方法引用
        //className::func
    

设计模式学习笔记

设计模式系列学习视频

CodeChina开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》

ram2) -> source.substring(param1,param2);
//直接使用方法引用
//className::func

设计模式学习笔记

[外链图片转存中…(img-7Jt4nQAl-1630931419562)]

设计模式系列学习视频

[外链图片转存中…(img-U8D53lRV-1630931419564)]

CodeChina开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值