java8学习:通过行为参数化传递代码

简介: 内容来自《 java8实战 》,本篇文章内容均为非盈利,旨为方便自己查询、总结备份、开源分享。如有侵权请告知,马上删除。书籍购买地址:[java8实战] 如下一段代码请看 @Test public void test() throws Exception { List li.

内容来自《 java8实战 》,本篇文章内容均为非盈利,旨为方便自己查询、总结备份、开源分享。如有侵权请告知,马上删除。
书籍购买地址:java8实战

  • 如下一段代码请看

    @Test
    public void test() throws Exception {
        List<Apple> list = new ArrayList<>();
        for (Apple apple : list) {
            if (apple.getWeight() > 1000){
                System.out.println("...");
            }
        }
    }
    • 这段代码再简单不过了,并且完成了该完成的判断条件,但是如果现在并不是想判断重量weight了,而是需要判断color是不是红色的了,那么就只能代码复制然后改条件了,如下
    @Test
    public void test() throws Exception {
        List<Apple> list = new ArrayList<>();
        for (Apple apple : list) {
            if ("red".equals(apple.getColor())){
                System.out.println("...");
            }
        }
    }
    • 此时发现,除了更改了if条件,其他地方是没有动的,但是如果我又需要更改别的条件呢,无奈只好再次变换if条件,针对这一的情况,java8的行为参数化就可以处理频繁的变更
  • 行为参数化

    • 如上的筛选苹果颜色的代码,这时候我突然想要绿色的或者彩虹色可咋办难道还要拷贝?
            public void getAppleByColor(List<Apple> apples,String color){
                for (Apple apple : apples) {
                    if (color.equals(apple.getColor())){
                        System.out.println("...");
                    }
                }
            }
    //getAppleByColor(lists,"red");     //调用
    • 上面这段代码就解决了一直变更的颜色的问题,任他来的是透明颜色都没问题,并且调用方法时,也可以清晰的看出来我们需要的是什么苹果
    • 苹果大卖钱就多,那么如果按照重量筛选呢?代码已经给出来了,那么就是开篇的第二段代码,仔细想一下虽然解决了我们的问题,但是是不是代码重复的太多了,并且这样的编程风格十分不好,违反了DRY(don't repeat yourself),这时候我们就可能想到了进一步的解决办法来应对重量和颜色的不同选择,那就是立flag,如下
public void getAppleByColor(List<Apple> apples,String color,Integer weight,boolean isColor){
    for (Apple apple : apples) {
        if ((isColor && color.equals(apple.getColor())) ||
            !isColor && weight > apple.getWeight()){
            System.out.println("...");
        }
    }
}
getAppleByColor(lists,"red",0,true);       //调用
getAppleByColor(lists,"",123,false);       //调用
  • 如上,调用简直不能再糟了,如果不让调用者看到方法的方法签名和解释,那么他肯定不会知道true代表啥false代表啥,所以这种方法解决此问题是十分不可取的,那么我们肯定就需要更好的解决方案
  • 思路:建立一个接口,那么就有类去实现接口,那么每个实现类不就代表一种行为吗?比如这样改
interface FilterApple{
    boolean filter(Apple apple);
}
class FilterRedApple implements FilterApple{
    @Override
    public boolean filter(Apple apple) {
        return "red".equals(apple.getColor());
    }
}
class FilterAppleByWeight implements FilterApple{
    @Override
    public boolean filter(Apple apple) {
        return apple.getWeight() > 1000;
    }
}
public class Java8 {
    @Test
    public void test() throws Exception {
        List<Apple> apples = Arrays.asList();
        getAppleByColor(apples,new FilterAppleByWeight());
        getAppleByColor(apples,new FilterRedApple());
    }

    public void getAppleByColor(List<Apple> apples,FilterApple filter){
        for (Apple apple : apples) {
            if (filter.filter(apple)) {
                System.out.println("....");
            }
        }
    }
}
  • 如上代码有点长但是十分的简单,在上面我们可以看到,我们利用了多态的特性来用不同的实现类来实现不同需求的过滤,如果以后把苹果分男女,那么我们只需要增加一个FilterAppleByJJ就可以了
  • 引出:如上就是一种行为参数化,让方法接受多种行为作为参数,并在内部使用,来完成不同的行为
  • 在上面的例子中,唯一重要的也就是filter的实现,但是我们写的方法只能接受一个FilterApple对象,所以必须把不同的实现代码包裹在此对象中。这就好像你借别人钱还要拿纸包起来,不仅老套而且人家关心的只是钱的问题,纸随便就给扔掉了,在这我们不同实现类中的实现的不同逻辑就是借的钱,就比如下面这样

markdown_img_paste_20181106090528506

  • 但是对于上面的写法有点太啰里啰嗦的了,实现一个过滤就要实现一个接口?这时候就应该能想到匿名内部类了把~
@Test
public void test() throws Exception {
    List<Apple> apples = Arrays.asList();
    getAppleByColor(apples, new FilterApple() {
        @Override
        public boolean filter(Apple apple) {
            return apple.getWeight() > 1000;
        }
    });
}
public void getAppleByColor(List<Apple> apples,FilterApple filter){
    for (Apple apple : apples) {
        if (filter.filter(apple)) {
            System.out.println("....");
        }
    }
}
  • 但是匿名内部类还是存在很多的问题,1.就是样本代码太多,2.那么就是不清楚,比如下面这个,你来看看输出什么,答案在最下面
public class Java8 {
    private final int value = 4;
    public void doIt(){
        int value = 6;
        Runnable runnable = new Runnable() {
            public final int value = 5;
            @Override
            public void run() {
                int value = 10;
                System.out.println(this.value);
            }
        };
        runnable.run();
    }

    public static void main(String[] args) {
        new Java8().doIt();
    }
}
  • 匿名内部类的弊端:在只需要传递一段简单的代码时,还是需要创建一个对象,明确的实现一个方法来定义一个新的行为
  • 上面的问题来充实Lambda表达式解决

    @Test
    public void test() throws Exception {
        List<Apple> apples = Arrays.asList();
        getAppleByColor(apples,(apple) -> apple.getWeight() > 1000);
    }
    
    public void getAppleByColor(List<Apple> apples,FilterApple filter){
        for (Apple apple : apples) {
            if (filter.filter(apple)) {
                System.out.println("....");
            }
        }
    }
    • 爽的一批,对于lambda以后会继续说的
    • 但是还有个问题,这个只能是过滤Apple把,如果我还有西瓜之类的呢,那么代码就可以引入泛型T
interface Filter<T>{
    boolean filter(T t);
}
public class Java8 {
        @Test
        public void test() throws Exception {
            List<Apple> apples = Arrays.asList();
            getAppleByColor(apples,apple -> apple.getWeight() > 1000);
        }

        public <T> void getAppleByColor(List<T> ts,Filter<T> filter){
            for (T t : ts) {
                if (filter.filter(t)){
                    System.out.println("...");
                }
            }
        }
}
  • 这时候就想过滤什么就过滤什么了
Comparator排序
@Test
public void test() throws Exception {
    List<Apple> apples = Arrays.asList();
    apples.sort(Comparator.comparing(Apple::getWeight));
}
or
@Test
public void test() throws Exception {
    List<Apple> apples = Arrays.asList();
    apples.sort((a1,a2) -> a1.getWeight().compareTo(a2.getWeight()));
}
  • Runnable
@Test
public void test() throws Exception {
    Runnable runnable = ()->{
        System.out.println("run");
    };
    runnable.run();
}
  • 好了上面是两个例子仅供参考
  • 答案:5
目录
相关文章
|
14天前
|
安全 Java 编译器
深入理解Java中synchronized三种使用方式:助您写出线程安全的代码
`synchronized` 是 Java 中的关键字,用于实现线程同步,确保多个线程互斥访问共享资源。它通过内置的监视器锁机制,防止多个线程同时执行被 `synchronized` 修饰的方法或代码块。`synchronized` 可以修饰非静态方法、静态方法和代码块,分别锁定实例对象、类对象或指定的对象。其底层原理基于 JVM 的指令和对象的监视器,JDK 1.6 后引入了偏向锁、轻量级锁等优化措施,提高了性能。
40 3
|
2月前
|
Java
java小工具util系列4:基础工具代码(Msg、PageResult、Response、常量、枚举)
java小工具util系列4:基础工具代码(Msg、PageResult、Response、常量、枚举)
58 24
|
22天前
|
前端开发 Java 测试技术
java日常开发中如何写出优雅的好维护的代码
代码可读性太差,实际是给团队后续开发中埋坑,优化在平时,没有那个团队会说我专门给你一个月来优化之前的代码,所以在日常开发中就要多注意可读性问题,不要写出几天之后自己都看不懂的代码。
57 2
|
1月前
|
Java 编译器 数据库
Java 中的注解(Annotations):代码中的 “元数据” 魔法
Java注解是代码中的“元数据”标签,不直接参与业务逻辑,但在编译或运行时提供重要信息。本文介绍了注解的基础语法、内置注解的应用场景,以及如何自定义注解和结合AOP技术实现方法执行日志记录,展示了注解在提升代码质量、简化开发流程和增强程序功能方面的强大作用。
82 5
|
1月前
|
存储 算法 Java
Java 内存管理与优化:掌控堆与栈,雕琢高效代码
Java内存管理与优化是提升程序性能的关键。掌握堆与栈的运作机制,学习如何有效管理内存资源,雕琢出更加高效的代码,是每个Java开发者必备的技能。
57 5
|
2月前
|
Java API 开发者
Java中的Lambda表达式:简洁代码的利器####
本文探讨了Java中Lambda表达式的概念、用途及其在简化代码和提高开发效率方面的显著作用。通过具体实例,展示了Lambda表达式如何在Java 8及更高版本中替代传统的匿名内部类,使代码更加简洁易读。文章还简要介绍了Lambda表达式的语法和常见用法,帮助开发者更好地理解和应用这一强大的工具。 ####
|
1月前
|
安全 Java API
Java中的Lambda表达式:简化代码的现代魔法
在Java 8的发布中,Lambda表达式的引入无疑是一场编程范式的革命。它不仅让代码变得更加简洁,还使得函数式编程在Java中成为可能。本文将深入探讨Lambda表达式如何改变我们编写和维护Java代码的方式,以及它是如何提升我们编码效率的。
|
8月前
|
存储 安全 Java
24、使用 Java 官方教程学习:① 类变量和类方法详解;② 深入介绍 main() 方法
24、使用 Java 官方教程学习:① 类变量和类方法详解;② 深入介绍 main() 方法
107 1
|
8月前
|
存储 Java
【JAVA学习之路 | 进阶篇】Map接口及其实现类及常用方法
【JAVA学习之路 | 进阶篇】Map接口及其实现类及常用方法
|
8月前
|
Java 测试技术 C++
【JAVA学习之路 | 进阶篇】File类及常用方法
【JAVA学习之路 | 进阶篇】File类及常用方法