【Java面向对象】匿名类(代码传递_测试代码运行时间的工具类、过滤器_简易网络请求、回调_获取目录下的所有文件)_排序(Array.sort())、Lambda、方法引用

面向对象

匿名类

当接口、抽象类的实现类,在整个项目中只用过一次,可以考虑使用匿名类

案例

    public interface Eatable {
        String name();
        int energy();
    }
    public class Person {
        public void eat(Eatable a) {
            System.out.println("eat - " + a.name() + " -" + a.energy());
        }
    }
    public static void main(String[] args) {
        Person person = new Person();
        person.eat(new Eatable() { // 匿名内部类
            @Override
            public String name() {
                return "Apple";
            }
            @Override
            public int energy() {
                return 100;
            }
        }); // eat - Apple -100

        Eatable beef = new Eatable() {
            @Override
            public String name() {
                return "Beef";
            }
            @Override
            public int energy() {
                return 200;
            }
        };
        person.eat(beef); // eat - beef -200

    }

基本使用

匿名类不能定义除 编译时常量(static int final a = 1) 以外的任何 static 成员

在这里插入图片描述

匿名类只能访问 final 或者 有效final的局部变量

有效 final 的局部变量” 就是指只被赋值过一次的局部变量

在这里插入图片描述

匿名类可以直接访问外部类中的所有成员(即使被声明为 private)

匿名类只有在实例相关的代码块中使用,才能直接访问外部类中的实例成员(实例变量、实例方法)

匿名类不能自定义构造方法,但可以有初始化块

在这里插入图片描述

用途

匿名类的常见用途

  • 代码传递
  • 过滤器
  • 回调

匿名类 - 代码传递 - 测试代码运行时间的工具类

    public class Times {
        public interface Block {
            void execute();
        }

        public static void test(Block block) {
            long begin = System.currentTimeMillis();
            block.execute();
            long end = System.currentTimeMillis();
            long duration = end - begin;
            System.out.println("花费时间" + duration + "ms");
        }
    }

小提示:字符串拼接相当耗时

    public static void main(String[] args) {
        Times.test(new Block() {
            @Override
            public void execute() {
                String str = "";
                for (int i = 0; i < 10000; i++) {
                    // 字符串拼接极其耗时间, 因为每次都相当于创建新的对象
                    str += i;
                }
            }
        });
    }

匿名类 - 回调 - 简易网络请求

public class Networks {
	
	public interface Block {
		void success(Object response);
		void failure();
	}
	
	public static void get(String url, Block callBack) {
		// 1. 根据url发送一个异步请求(开启一条子线程)
		// ......
		// 2. 请求完毕后
		boolean result = url.contains("666") ? true : false;
		if (result) {
			Object response = null;
			callBack.success(response);
		} else {
			callBack.failure();
		}
	}
	
	public static void main(String[] args) {
		// 传入的网络请求只有满足某些条件时会返回成功, 其他情况会失败
		// 但是发送请求时将成功要做的事的和失败要做的事都写好了
		// 等到判断条件是否满足以后再回来调用, 这就是回调
		Networks.get("http://xxx.com?pwd=666", new Block() {
			@Override
			public void success(Object response) {
				System.out.println("请求成功");
			}
			@Override
			public void failure() {
				System.out.println("请求失败");
			}
		});
	}		
}

匿名类 - 过滤器 - 获取目录下的所有文件

    public class Files {
        public interface Filter {
            boolean accpet(String filename);
        }

        // 需要传入一个Filter过滤器, 用来自定义要返回满足哪些条件的文件名
        public static String[] getAllFileNames(String dir, Filter filter) {

            // 1.先获取 dir 文件夹下的所有文件名
            String[] allFilesnames = {};
            // 2.进行过滤
            for (String filename : allFilesnames) {
                if (filter.accpet(filename)) {
                    // 将满足条件的文件名装起来
                }
            }
            // 返回所有装起来的文件名(满足条件的文件名)
            return null;
        }

        public static void main(String[] args) {
            // 获取F盘下所有.java文件
            Files.getAllFileNames("F:", new Filter() {
                @Override
                public boolean accpet(String filename) {
                    if (filename.endsWith(".java")) return true;
                    return false;
                }
            });
            // 获取F盘下所有名字中带hello的文件
            Files.getAllFileNames("F:", new Filter() {
                @Override
                public boolean accpet(String filename) {
                    if (filename.contains("hello")) return true;
                    return false;
                }
            });
        }
    }

排序

Arrays.sort()

可以使用 JDK 自带的 java.util.Arrays 类中的sort()方法对数组进行排序;

  • Arrays.sort 默认是升序排列,可以通过比较器 Comparator 改变次序
    • 把比较小的元素放左边
    • 把比较大的元素放右边
  • compare的返回值
    • 等于 0 : o1 == o2
    • 大于 0 : o1 > o2
    • 小于 0:o1 < o2
    Integer[] array = { 33, 22, 11, 77, 66, 99 };
    Arrays.sort(array);
    System.out.println(Arrays.toString(array));
    // [33, 22, 11, 77, 66, 99]

    Arrays.sort(array, new Comparator<Integer>() {
        @Override
        public int compare(Integer o1, Integer o2) {
            return o1 - o2;
        }
    });

    System.out.println(Arrays.toString(array));
    // [11, 22, 33, 66, 77, 99]

Lambda

基本使用

Lambda 表达式是 Java 8 开始才有的语法

  • 函数式接口(Functional Interface):只包含 1 个抽象方法的接口
    可以在接口上面加上 @FunctionalInterface 注解,表示它是一个函数式接口
  • 当匿名类实现的是函数式接口时,可以使用 Lambda 表达式进行简化
    @FunctionalInterface
    public interface Testable {
        void test(int v);
    }

注意事项

  • 参数列表可以省略参数类型
  • 当只有一条语句时,可以省略大括号、分号、return
  • 当只有一个参数时:可以省略小括号
  • 没有参数时:不能省略小括号

Lambda 表达式示例

    public interface Caculator {
        int caculate(int v1, int v2);
    }

    static void execute(int v1, int v2, Caculator c) {
        System.out.println(c.caculate(v1, v2));
    }

    public static void main(String[] args) {	
        execute(10, 20, (int v1, int v2) -> {
            return v1 + v2; // 20
        });
        execute(11, 22, (v1, v2) -> v1 + v2); // 20
    }

使用注意

使用注意

  • Lambda 只能访问 final 或者 有效 final 的局部变量
  • Lambda 没有引入新的作用域
    public class OuterClass {

        @FunctionalInterface
        public interface Testable {
            void test(int v);
        }

        private int age = 1;

        public class InnerClass {
            private int age = 2;
            void inner() {
                // int v = 4; // error, Lambda 没有引入新的作用域, 重复定义变量

                Testable t1 = v -> {
                    System.out.println(v); // 3
                    System.out.println(age); // 2
                    System.out.println(this.age); // 2
                    System.out.println(InnerClass.this.age); // 2
                    System.out.println(OuterClass.this.age); // 1
                };
                t1.test(3);

                Testable t2 = new Testable() {
                    @Override
                    public void test(int v) {
                        System.out.println(v); // 3
                        System.out.println(age); // 2
                        // System.out.println(this.age); // error
                        System.out.println(InnerClass.this.age); // 2
                        System.out.println(OuterClass.this.age); // 1
                    }
                };
                t2.test(3);

            }
        }

        public static void main(String[] args) {
            new OuterClass().new InnerClass().inner();
        }	
    }

方法引用

如果 Lambda 中的内容仅仅是调用某个方法,可以使用方法引用(Method Reference)来简化

在这里插入图片描述

引用静态方法

    @FunctionalInterface
    public interface Testable {
        int test(int v1, int v2);
    }

    public static void main(String[] args) {
        Testable t1 = (v1, v2) -> Math.max(v1, v2); 
        System.out.println(t1.test(10, 20)); // 20

        Testable t2 = Math::max; // 引用静态方法
        System.out.println(t2.test(10, 20)); // 20
    }

引用特定对象的实例方法

    @FunctionalInterface
    public interface Testable {
        void test(int v);
    }

    public class Person {
        public void setAge(int age) {
            System.out.println("Person - setAge - " + age);
        }
        static void execute(Testable t, int v) {
            t.test(v);
        }
        public static void main(String[] args) {
            // 10
            execute(v -> System.out.println(v), 10);
            // 20
            execute(System.out::println, 20); // 引用特定对象的实例方法

            // Person - setAge - 10
            execute(v -> new Person().setAge(v), 10);
            // Person - setAge - 20
            execute(new Person()::setAge, 20); // 引用特定对象的实例方法
        }
    }

引用特定类型的任意对象的实例方法

    String[] strings = { "Jack", "james", "Apple", "abort" };
    // [abort, Apple, Jack, james]
    Arrays.sort(strings, (s1, s2) -> s1.compareToIgnoreCase(s2));

    // [abort, Apple, Jack, james]
    Arrays.sort(strings, String::compareToIgnoreCase); // 引用特定类型的任意对象的实例方法

引用构造方法

    public class Person {
        @FunctionalInterface
        public interface Testable {
            Object test(int v);
        }
        public Person(int age) { // 构造方法
            System.out.println("Person - " + age);
        }
        public static void main(String[] args) {
            Testable t1 = v -> new Person(v);
            // Person - 18
            // com.mj.Person@816f27d
            System.out.println(t1.test(18)); 

            // Person - 18
            // com.mj.Person@6ce253f1
            Testable t2 = Person::new; // 引用构造方法
            System.out.println(t2.test(18));
        }
    }

引用数组的构造方法

    @FunctionalInterface
    public interface Testable {
        Object test(int v);
    }

    public static void main(String[] args) {
        Testable t1 = v -> new int[v];
        System.out.println(((int[])t1.test(3)).length);

        Testable t2 = int[]::new; // 引用数组的构造方法
        System.out.println(((int[])t2.test(3)).length);

引用当前类中定义的实例方法

    public class Person {
        public void setAge(int age) {
            System.out.println("Person - setAge - " + age);
        }
        public void show() {
            Testable t1 = v1 -> setAge(v);
            // Person - setAge - 10
            t1.test(10);

            Testable t2 = this::setAge; // 引用当前类中定义的实例方法
            // Person - setAge - 10
            t2.test(10);
        }
    }

引用父类中定义的实例方法

    @FunctionalInterface
    public interface Testable {
        void test(int v);
    }
    class Person {
        public void setAge(int age) {
            System.out.println("Person - setAge - " + age);
        }
    }
    public class Studen extends Person {
        public void setAge(int age) {
            System.out.println("Student - setAge - " + age);
        }
        public void show() {
            Testable t1 = v -> super.setAge(v);
            // Student - setAge - 10
            t1.test(10);

            Testable t2 = super::setAge; // 引用父类中定义的实例方法
            // Student - setAge - 10
            t2.test(10);
        }
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值