方法的引用是用来直接访问类或者实例的已经存在的方法或者构造方法,方法引用提供了一种引用而并不执行方法的方式,如果抽象方法的实现恰好可以使用调用另一种方法来实现,就有可能可以使用方法引用。
方法的引用分为四种类型
静态方法引用
实例方法引用
对象方法引用
构造方法引用
静态方法引用
如果函数式接口的实现恰好可以通过调用一个静态方法来实现,那么就可以使用静态方法引用。
package com.per.lambada;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
class Foo{
public static String ret() {
System.out.println("put method invoke");
return "ret hello";
}
public static void con(int size) {
System.out.println("size:"+size);
}
static String fun(String str) {
return str.toUpperCase();
}
}
public class Test{
public static int put() {
return 23;
}
public static void main(String[] args) {
// 调用本类中的静态方法的引用
Supplier<Integer> s= ()->Test.put();
// 可以简化成::
Supplier<Integer> s1= Test::put;
// 调用非本类中的静态方法的引用
Supplier<String> s2=Foo::ret;
System.out.println(s.get());
System.out.println(s2.get());
// 有参无返回值
Consumer<Integer> con1 = size -> Foo.con(size);
Consumer<Integer> con2 = Foo::con;
con2.accept(100);
// 有参有返回值
Function<String,String> fun1 = str -> Foo.fun(str);
Function<String,String> fun2 = Foo::fun;
System.out.println(fun2.apply("zhangsan"));
}
}
23
put method invoke
ret hello
size:100
ZHANGSAN
实例方法的引用
如果函数式接口的实现恰好可以通过调用一个实例的实例方法来实现,那么就可以使用实例方法引用
Example3 .java
package com.edu.java8.lambda;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
/**
* 实例方法引用
* 如果函数式接口的实现恰好可以通过调用一个实例的实例方法来实现,那么就可以使用实例方法引用
*
* 语法
* inst::instMethod
*/
public class Example3 extends Base {
public String put() {
return "hello";
}
public void con(Integer size) {
System.out.println("size : " + size);
}
public String toUpper(String str) {
System.out.println("current to upper");
return str.toUpperCase();
}
public void test() {
Function<String, String> f4 = this::toUpper;
System.out.println(f4.apply("javame"));
Function<String, String> f5 = super::toUpper;
System.out.println(f5.apply("javame"));
}
public static void main(String[] args) {
Supplier<String> s = () -> new Example3().put();
Supplier<String> s1 = () -> {return new Example3().put();};
Supplier<String> s2 = new Example3()::put;
System.out.println(s2.get());
Example3 exam = new Example3();
exam.test();
Consumer<Integer> c1 = (size) -> new Example3().con(size);
Consumer<Integer> c2 = new Example3()::con;
Consumer<Integer> c3 = exam::con;
c2.accept(100);
c3.accept(100);
Function<String, String> f1 = str -> str.toUpperCase();
Function<String, String> f2 = str -> exam.toUpper(str);
Function<String, String> f3 = str -> new Example3().toUpper(str);
Function<String, String> f4 = exam::toUpper;
Function<String, String> f5 = new Example3()::toUpper;
System.out.println(f4.apply("javase"));
System.out.println(f5.apply("javaee"));
}
}
Base.java
public class Base {
public String toUpper(String str) {
System.out.println("base to upper");
return str.toUpperCase();
}
}
在实例方法引用中是可以使用this和super关键字的。
对象方法的引用
抽象方法的第一个参数类型刚好是实例方法的类型,抽象方法剩余的参数恰好可以当做实例方法的参数。如果函数式接口的实现能由上面说的实例方法调用来实现的话,那么就可以适用对象方法引用。
package com.edu.java8.lambda;
import java.io.Closeable;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Supplier;
/**
* 对象方法引用
* 抽象方法的第一个参数类型刚好是实例方法的类型,抽象方法剩余的参数恰好可以当做实例方法的参数。
* 如果函数式接口的实现能由上面说的实例方法调用来实现的话,那么就可以使用对象方法引用
*
*
* 第一个参数类型 最好是自定义的类型
*
* 语法
* 类名::instMethod
*/
public class Example4 {
/**
* 抽象方法没有输入参数,不能使用对象方法引用
* 比如说,如下函数式接口
*/
public void not() {
Runnable run = () -> {};
Closeable c = () -> {};
Supplier<String> s = () -> "";
}
public static void main(String[] args) {
Consumer<Too> c1 = (Too too) -> new Too().foo();
Consumer<Too> c2 = (Too too) -> new Too2().foo();
Consumer<Too> c3 = Too::foo;
c1.accept(new Too());
c3.accept(new Too());
BiConsumer<Too2, String> c5 = (too2, str) -> new Too2().fo(str);
BiConsumer<Too2, String> c6 = Too2::fo;
BiFunction<Prod, String, Integer> bf1 = (p, s) -> new Prod().fun(s);
BiFunction<Prod, String, Integer> bf2 = (p, s) -> new Too().fun(s);
BiFunction<Prod, String, Integer> bf3 = Prod::fun;
Execute ex1 = (p,name,size) -> new Prod().run(name, size);
Execute ex2 = Prod::run;
}
}
interface Execute {
public void run(Prod p, String name, String size);
}
class Prod {
public void run(String name, String size) {
}
public Integer fun(String s) {
return 1;
}
}
class Too {
public Integer fun(String s) {
return 1;
}
public void foo() {
System.out.println("invoke");
}
}
class Too2 {
public void foo() {
System.out.println("invoke");
}
public void fo(String str) {
}
}
构造方法的引用
如果函数式接口的实现恰好可以通过调用一个类的构造方法来实现,那么就可以使用构造方法引用
package com.edu.java8.lambda;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
/**
* 构造方法引用
* 如果函数式接口的实现恰好可以通过调用一个类的构造方法来实现,那么就可以使用构造方法引用
*
*
* 语法
* 类名::new
*/
public class Example5 {
public static void main(String[] args) {
Supplier<Person> s1 = () -> new Person();
Supplier<Person> s2 = Person::new;
s1.get();
s2.get();
Supplier<List> s3 = ArrayList::new;
Supplier<Thread> s4 = Thread::new;
Supplier<Set> s5 = HashSet::new;
Supplier<String> s6 = String::new;
Consumer<Integer> c1 = (age) -> new Account(age);
Consumer<Integer> c2 = Account::new;
c2.accept(123);
Function<String, Integer> fu = (str) -> Integer.valueOf(str);
Function<String, Integer> fu1 = Integer::valueOf;
Function<String, Account> fu2 = (str) -> new Account();
Function<String, Account> fu3 = Account::new;
fu3.apply("admin");
}
}
class Account {
public Account() {
System.out.println("Account");
}
public Account(int age) {
System.out.println("Account(age)");
}
public Account(String name) {
System.out.println("Account(name)");
}
}
class Person {
public Person() {
System.out.println("new Person()");
}
}
网友评论