匿名内部类+lambda表达式+方法引用

匿名内部类

new Swim() {
	@override
	public void swim() {
		...
	}
}

这段代码得到了一个实现了Swim接口的类的对象
常用该对象作为一些方法的参数
比如TreeSet的有参构造中需要传入的比较器对象

TreeSet<Teacher> ts = new TreeSet<>(new Comparator<Teacher>() {
            @Override
            public int compare(Teacher o1, Teacher o2) {
                ...
            }
        });

lambda表达式

承然,使用匿名内部类已经简化了参数的传递,不然,需要另创建一个类实现接口,重写方法,并new一个对象再传递。

但如果要实现的接口是函数式接口,即接口有@FunctionalInterface注解,要求该接口有且仅有一个抽象方法
我们就可以用lambda表达式进一步简化

// 可以ctrl+b查看Comparator,可以看到有@FunctionalInterface注解,
// 即comparator接口有且只有一个抽象方法
// 故可用lambda表达式简化匿名内部类的写法
TreeSet<Teacher> ts = new TreeSet<>((o1, o2) -> {
	...
});

lambda表达式形似js中箭头函数的形式,这里表示的是一个接口的实现类对象
因为该接口只有一个抽象方法,故可以用这样一个“函数”表示这个接口,
实际上lambda表达式表示的就是这个唯一的抽象方法

lambda表达式简写规则

  • 参数类型可以不写
  • 只有一个参数()可以不写
  • 函数体只有一行可以不用写{},默认编译为 return 这一行

方法引用

某些情况还可以使用方法引用,避免逻辑的重复书写,使更加简洁

  • 方法引用符
    :: 该符号为引用运算符,而它所在的表达式被称为方法引用
  • 推导与省略
    • 如果使用Lambda,那么根据“可推导就是可省略”的原则,无需指定参数类型,也无需指定的重载形式,它们都将被自动推导
    • 如果使用方法引用,也是同样可以根据上下文进行推导

方法引用分为,引用类方法引用对象的实例方法引用类的实例方法引用构造器

  1. 引用类方法
public interface Converter {
    int convert(String s);
}

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

		//Lambda写法
        useConverter(s -> Integer.parseInt(s));

        //引用类方法
        useConverter(Integer::parseInt);

    }

    private static void useConverter(Converter c) {
        int number = c.convert("666");
        System.out.println(number);
    }
}

引用类方法,引用的是类的静态方法
AClass::fun表示用 T Aclass.fun(args)函数代表一个函数式接口的实现类对象
参数和返回值必须和要实现的接口中的抽象方法对应
  1. 引用对象的实例方法
public class PrintString {
    //把字符串参数变成大写的数据,然后在控制台输出
    public void printUpper(String s) {
        String result = s.toUpperCase();
        System.out.println(result);
    }
}

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

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

		//Lambda简化写法
        usePrinter(s -> System.out.println(s.toUpperCase()));

        //引用对象的实例方法
        PrintString ps = new PrintString();
        usePrinter(ps::printUpper);

    }

    private static void usePrinter(Printer p) {
        p.printUpperCase("HelloWorld");
    }
}

引用对象的实例方法
obj::fun 表示用 实例obj的fun方法代表一个函数式接口的实现类对象
参数和返回值必须和要实现的接口中的抽象方法对应
  1. 引用类的实例方法
public interface MyString {
    String mySubString(String s,int x,int y);
}

public class MyStringDemo {
    public static void main(String[] args) {
		//Lambda简化写法
        useMyString((s,x,y) -> s.substring(x,y));

        //引用类的实例方法
        useMyString(String::substring);

    }

    private static void useMyString(MyString my) {
        String s = my.mySubString("HelloWorld", 2, 5);
        System.out.println(s);
    }
}

引用类的实例方法,引用类的非静态方法
要求该类是接口的抽象方法中的第一个参数类型,后面参数依次对应
如用String::substring表示一个函数式接口的实现类对象
该接口的抽象方法需满足,传入的参数分别是Stringintint,返回值为String
  1. 引用构造器
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;
    }
}

public interface StudentBuilder {
    Student build(String name,int age);
}

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

		//Lambda简化写法
        useStudentBuilder((name,age) -> new Student(name,age));

        //引用构造器
        useStudentBuilder(Student::new);

    }

    private static void useStudentBuilder(StudentBuilder sb) {
        Student s = sb.build("林青霞", 30);
        System.out.println(s.getName() + "," + s.getAge());
    }
}

引用构造器,引用类的构造方法
如用Student::new表示一个函数式接口的实现类对象
那么该接口的抽象方法应满足,返回值为Student,
对参数的要求是,能在Student的构造方法中能找到一个参数列表相同的

你可能感兴趣的:(Java,java,jvm,开发语言)