方法引用使用

在Lambda表达式的时候,我们实际上传递进去的代码就是一种解决方案: 那参数做操作.Lambda = (参数类型 参数)->{执行语句…}
方法引用总结
就是在Lambda表达式的基础上 再次将参数传给方法引用,并省略该参数
例如:
Lambda表达式: usePrint(i -> System.out.println(i));
方法引用表达式: usePrint(System.out::println);
—> 省略了i这个参数, 将 i 这个参数传给了方法引用表达式(::)

那么考虑一种情况:
如果我们在Lambda中所指定的操作方案, 已经在别的地方存在相同的方案,是否还有必要重写逻辑呢? 答案是没有必要
那么如何使用已经存在的方案呢? 答案就是使用方法引用, 我们是通过方法引用来使用已经存在的方案
public interface Printable { void printString(String s);}
—————————————————————————-
public class PrintableDemo {
public static void main(String[] args) {
// 所有代码中可以被推演出来的都是可以省略的这就是方法引用的核心理念
// 标准Lambda表达式
usePrint((String s)->{ System.out.println(s); });
// 只有一个参数 一个输出语句 简化Lmabda
usePrint(s-> System.out.println(s));
// 使用方法引用符号:: 简化Lambda表达式
usePrint(System.out::println); }
private static void usePrint(Printable p){
p.printString(“hello,world”); } }

方法引用符(::)

方法引用符介绍

  • :: 该符号为引用运算符。而它所在的表达式被称为方法引用

    方法引用代码分析:

  • Lambda表达式:uesPrintable(s-> sout(s))

    • 分析: 拿到参数s之后通过Lambda表达式, 传递给System.out.println方法处理
  • 方法引用代码: uesPrintable(System.out::println)

    • 分析; z直接使用System.out中的println方法来取代Lambda,代码更整洁

      推导与省略

  • 如果使用Lambda. 那么根据”可推倒就是可省略”的原则. 无需指定参数类型. 也无需指定方法的重载形式. 这些元素都将被自动推导出来

  • 如果使用方法引用, 同样也可以根据上下文进行推导
  • 方法引用和Lamdba 是共生关系, Lambda可以推倒的如果有同样的方案也同样可以使用方法引用::

public interface Printable { void printString(int i);}
—————————————————————-
public class PrintableDemo {
public static void main(String[] args) {
// 所有代码中可以被推演出来的都是可以省略的这就是方法引用的核心理念
// 只有一个参数 一个输出语句 简化Lmabda
usePrint(i -> System.out.println(i));
// 使用方法引用符号:: 简化Lambda表达式
usePrint(System.out::println); }
private static void usePrint(Printable p){
p.printString(666); } }

Lambda表达式支持的方法引用

常见的引用方式:

  1. - **引用类方法**
  2. - **引用对象的实例方式**
  3. - **引用类的实例方法**
  4. - **引用构造器**

引用类方法

引用类方法,其实就是引用类的静态方法

  1. - **格式: 类名:: 静态方法**
  2. - **范例: Integer(类)::parseInt**
  3. - **Integer类的方法: public static int parseInt(String s)将String转换为int类型**

实例:

  1. - **定义一个接口(Converter), 里面定义一个抽象方法**
  2. - **int convert(String s);**
  3. - **定义一个测试类(ConverterDemo), 在测试类中提供两个方法**
  4. - **一个方法是: useConverter(Converter c)**
  5. - **一个方法是主方法. 在主方法中调用useConverter方法**

public interface Printable { int printString(int i);}
—————————————————————-
public class ConverterDemo {
public static void main(String[] args) {
// 使用Lambda表达式表示,使用Integer.parseInt转换String
// 因为方法规定了返回值类型为int所以需要回调函数return
useConverter((String s)-> {
return Integer.parseInt(s);
});
// 优化Lambda表达式
useConverter(s->Integer.parseInt(s));
// 直接使用方法引用类实现 Integer::parseInt
// 引用类替代Lambda的原理是,Lambda的形式参数全部传递给引用类的静态方法作为参数
useConverter(Integer::parseInt); }
private static void useConverter(Converter c){
int num = c.convert(“666”);
System.out.println(num); } }

引用对象的实例方法

引用对象的实例方法,其实就是引用类的成员方法

  1. - **格式: 对象:: 成员方法**
  2. - **范例: "HelloWorld"(对象的方法)::toUpperCase**
  3. - **String类的方法: public String toUpperCase() String所有字符转换为大写**

实例:

  1. - **定义一个类(PrintString), 里面定义一个方法**
  2. - **public int printUpper(String s): 把字符串参数转换为大写,然后在控制台输出**
  3. - **定义一个接口(Printer), 里面定义一个抽象方法**
  4. - **void printUpperCase(String s)**
  5. - **定义一个测试类(PrinterDemo),在测试类中提供两个方法**
  6. - **一个是usePrinter(Printer p)**
  7. - **一个方法是主方法. 在主方法中调用usePrinter方法**

// 创建一个接口,里面定义一个带参抽象方法
public interface Printer { void printUpperCase(String s);}
—————————————————————————————
// 创建一个类,里面定义含有String的toUpperCase()方法
public class PrintString {
public void printUpper(String s){
// 使用String的toUpperCase()方法
String toUpperCase = s.toUpperCase();
System.out.println(toUpperCase); } }
———————————————————————————-
// 创建个测试类(PrinterDemo),在测试类中提供两个方法
public class PrinterDemo {
public static void main(String[] args) {
// 使用Lambda表达式转换大写
usePrinter(s -> System.out.println(s.toUpperCase()));
// 使用方法引用,因为已经在某一个类中定义了大写的方法,所以引用该类的实例对象的方法
usePrinter(s -> new PrintString().printUpper(s));
// 使用引用符号简写代码,先创建想要引用类的实例对象
// Lambda表达式被对象的实例方法替代是时候,就是讲整个类作为形参传递给方法引用作参数
// 所以可以直接使用该类的方法
PrintString ps = new PrintString();
usePrinter(ps::printUpper); }
private static void usePrinter(Printer p){
//使用方法引用调用toUpperCase()方法
p.printUpperCase(“hello,world”); } }

引用类的实例方法

引用类的实例方法,其实就是引用类的成员方法

  1. - **格式: 类名::成员方法**
  2. - **范例: String(类)::substring**
  3. - **String类的方法: public String substring(int beginIndex,omt endIndex)**
  4. - **从beginIndex开始到endIndex结束,截取字符串,返回一个子串,子串的长度为endIndex-beginIndex**

实例:

  1. - **定义一个接口(MyString), 里面定义一个抽象方法**
  2. - **String mySubString(String s,int x,int y): 截取字符串长度**
  3. - **定义一个测试类(MyStringDemo),在测试类中提供两个方法**
  4. - **一个是useMyString(MyString ms)**
  5. - **一个方法是主方法. 在主方法中调用useMyString方法**

public interface MyString { String mySuString(String s,int x,int y);}
——————————————————————————————————-
public class MyStringDemo {
public static void main(String[] args) {
// 匿名内部类实现,并返回值
useMyString(new MyString() {
@Override
_public String mySuString(String _s
, int x, int y) {
return s.substring(x,y); } });
// Lambda表达式标准
useMyString((String s,int x,int y)->{ return s.substring(x,y); });
// Lambda表达式简化
useMyString((s, x, y) -> s.substring(x,y));
// Lambda表达式使用方法引用类 ::简化
// 可以看出三个参数,最终是通过String参数的对象s
// 对象s调用String类中substring()这个方法,

// 将s和x,y传入给String类的substring()完成编译
// 所以可以推导出,String.substring(s,x,y),就得出如下String::substring方法引用格式

useMyString(String::substring);
// Lambda表达式被类的实例方法替代时
// 第一个参数座位调用者 (String类型的s参数 座位调用者)
// 后面的参数将全部传递给方法作为该方法的参数(int类型的x参数和y参数)
}
private static void useMyString(MyString ms) { System.out.println(ms.mySuString(“hello,world”,1,5)); } }

引用构造器

引用构造器,其实就是引用构造方法

  1. - **格式: 类名::new**
  2. - **范例: Student(类)::new**

实例:

  1. - **定义一个类(Student), 里面有两个成员变量(name,age)**
  2. - **并提供无参和带参构造方法, 以及成员变量对应的getset方法**
  3. - **定义一个接口(StudentBuilder),里面定义一个抽象方法**
  4. - **Student build(String name,int age)**
  5. - **定义一个方法是测试类(StudentDemo). 在测试类中提供两个方法**
  6. - **一个是: useStudentBuilder(StudentBuilder sb)**
  7. - **一个方法是主方法,在主方法中调用useStudentBuilder方法**

// 定义一个学生类
public class Student {
private String name;
private int 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 Student() { }
public Student(String name, int age) {
this.name = name;
this.age = age; }}
// 定义一个接口
public interface StudentBuilder {
// 定义一个抽象方法.定义返回值类型为Student类,两个形参
Student build(String name,int age); }
// 定义一个测试类,有两个方法
public class StudentDemo {
public static void main(String[] args) {
// 匿名内部类返回接口方法
useStudentBuilder(new StudentBuilder() {
@Override
_public Student build(String _name
, int age) {
return new Student(name, age); } });
// Lambda表达式返回接口方法
useStudentBuilder((String name, int age) -> {
// Student s = new Student();
// return s;
// 相当于返回一个新的学生对象
return new Student(name, age); });
// 简化Lambda表达式,省略参数类型,以及return关键字
useStudentBuilder((name, age) -> new Student(name, age));
// 引用构造器 — (类::new)
// Lambda表达式被构造器替代的时候,它的形式参数全部传递给构造器作为参数
// 用Lambda表达式将(name,age)两个参数传给方法引用,传来了新的学生类
useStudentBuilder(Student::new); }
public static void useStudentBuilder(StudentBuilder sb) {
Student 李畅 = sb.build(“李畅”, 20);
System.out.println(李畅.getName() + “,” + 李畅.getAge()); } }