java 详解匿名内部类与函数式接口

引言

匿名内部类也就是没有名字的内部类,正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写。
匿名内部类的前提必须是继承与类实现相应接口。匿名实现类的总体效果就是父类的子类对象或子接口的实现接口。
函数式接口:接口中只有一个抽象方法的接口 可以使用@FunctionalIterface进行标记。使用lambda表达式也可以看作函数式接口的一个实现子类

不使用匿名内部类

1 创建 Animal 的抽象类并提供eat 方法

 abstract class Animal{
    public abstract void eat();
}

2 定义一个dog 继承自Animal

class Dog extends  Animal{
    @Override
    public void eat() {
        System.out.println("狗吃屎");
    }
}

3 调用Dog 的eat 方法

public class demo_1 {
    public static void main(String[] args) {
		Dog dog=new Dog();
		dog.eat;
    }
}

问题: 如果要实现打印猫吃屎,还得需要实现cat 类并重写eat方法。这时就可以使用匿名内部类了。可以创建那么多的类。

匿名内部类的使用

new 类名/接口名(){
     重写抽象方法
    }

示例

 new Animal(){
        //重写抽象方法
        @Override
        public void eat() {
            System.out.println("狗吃肉");
        }
    }

整体等效于 Animal父类的子类对象

匿名内部类调用

直接调用eat 方法

new Animal(){
            //重写抽象方法
            @Override
            public void eat() {
                System.out.println("狗吃肉");
            }
        }.eat();

匿名函数调用的方式二

String mao="猫吃肉";//注意匿名内部类访问局部变量,jdk 8之前必须加final 关键字
Animal anminal = new Animal() {
    //重写抽象方法
    @Override
    public void eat() {
        System.out.println(mao);
    }
};
anminal.eat();

注意匿名内部类访问局部变量,jdk 8之前必须加final 关键字

匿名内部类举例

案例一:

new Thread(new Runnable(){
			@Override
			public void run(){
				System.out.println("Anonymous Class Thread run()");
			}
		}).start();

案例二:

Collections.sort(list, new Comparator<String>(){// 接口名
    @Override
    public int compare(String s1, String s2){// 方法名
        if(s1 == null)
            return -1;
        if(s2 == null)
            return 1;
        return s1.length()-s2.length();
    }
});

函数式接口

1 定义一个函数式接口

@FunctionalInterface
public interface myFunctionInterFace<T> {
    Integer count(T a,T b);
}

2 使用lambda表达式生成函数式接口的具体业务,生成具体子类,并调用

public class demo_1 {
    public static void main(String[] args) {
        // 有两种选择runnable 和D
        Runnable runnable = () -> System.out.println("你好");
        // 相当于返回一个类的实例
        myFunctionInterFace<Integer> myFun1 = (a, b) -> a + b;
        myFunctionInterFace<Integer> myFun2 = (a, b) -> a * b;
        myFunctionInterFace<Integer> myFun3 = (a, b) -> a - b;
        System.out.println(myFun1.count(45,7));
    }
}

自定义排序实战

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Emploee {

    private Integer id;
    private String name;
    private Integer age;
    private Double salary;
}
 List<Emploee> emps = Arrays.asList(
                new Emploee(101, "Z3", 19, 9999.99),
                new Emploee(102, "L4", 20, 7777.77),
                new Emploee(103, "W5", 35, 6666.66),
                new Emploee(104, "Tom", 44, 1111.11),
                new Emploee(105, "Jerry", 60, 4444.44)
        );
        // 使用匿名内部类重写comparate接口
        Collections.sort(emps, new Comparator<Emploee>() {
            @Override
            public int compare(Emploee o1, Emploee o2) {
                // 按照年龄从小到大排序
                return -(o1.getAge()-o2.getAge());
            }
        });
        // 使用lambda表达式, 薪水按照从低到高排序
        Collections.sort(emps,(o1,o2)->o1.getSalary()-o2.getSalary()>0?-1:1);
        for (Emploee e:emps){
            System.out.println(e);
        }

使用匿名函内部类和lambda重写Comparator 接口中的compare 方法。
运行结果
在这里插入图片描述


版权声明:本文为weixin_39802680原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。