目录
- 用 :: 引用方法
- 1. 4 种不同方法的引用
- 2. 常见使用情景
- a. 打印流:基于静态方法的引用
- b. 在泛型中的使用
- i. 引用方法
- ii. 引用构造方法
- 3. 与 Lambda 的比较
用 :: 引用方法
- Java 中,可以用
::
对方法和构造方法进行引用,借以改变指定对象的方法; - 方法引用通过方法的名字来指向一个方法;
- 方法引用可以使语言的构造更紧凑简洁,减少冗余代码;
1. 4 种不同方法的引用
- 可以直接引用类的构造方法、静态方法和特定对象的方法、特定类的任意对象的方法;
import java.util.Arrays;
import java.util.List;
//函数式接口(接口有且仅有一个抽象方法)
@FunctionalInterface
interface Supplier<T> {
T get();//代表创建行为,但只能创建固定的东西,所以很少使用
}
class Car {
public static Car create(final Supplier<Car> supplier) {
return supplier.get();
}
public static void collide(final Car car) {
System.out.println("Collided " + car.toString());//碰撞
}
public void follow(final Car another) {
System.out.println("Following the " + another.toString());
}
public void repair() {
System.out.println("Repaired " + this.toString());
}
public String toString() {
return "Car";
}
}
public class Test {
public static void main(String[] args) {
//1. 构造器引用,注意:这个构造器没有参数
final Car car = Car.create(Car::new);
//与 final Car car = new Car(); 等价
final List<Car> cars = Arrays.asList(car);
//2. 静态方法引用,注意:这个方法接受了一个Car类型的参数
cars.forEach(Car::collide);
//3. 特定对象的方法引用,注意:和静态方法引用一样,这个方法接受了一个Car类型的参数
final Car police = Car.create(Car::new);
cars.forEach(police::follow);
//4. 特定类的任意对象的方法引用,注意:这个方法没有定义入参
cars.forEach(Car::repair);
}
}
/*
输出
Collided Car
Following the Car
Repaired Car
*/
2. 常见使用情景
a. 打印流:基于静态方法的引用
- 使用
System.out::println
和 增强 for 快速输出支持迭代的集合:
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String args[]) {
List names = new ArrayList();
names.add("Google");
names.add("Runoob");
names.add("Taobao");
names.add("Baidu");
names.add("Sina");
names.forEach(System.out::println);
}
}
/*
输出
Google
Runoob
Taobao
Baidu
Sina
*/
也适用于流的使用:
流.forEach(System.out::println);
b. 在泛型中的使用
i. 引用方法
interface SI<String, Integer> {
Integer S(String string);
}
public class Test {
public static void main(String[] args) {
SI<String, Integer> st = Integer::valueOf;//引用Integer类的静态方法valueOf(),传递给st
// SI<String, Integer> st = new SI<String, Integer>() {
// @Override
// public Integer S(String s) {
// return Integer.valueOf(s);
// }
// };
System.out.println(st.S("100"));//对st.s()使用Integer类的valueOf(),将字符串转换为Integer类型
}
}
/*
输出
100
*/
ii. 引用构造方法
class Fruit {
private String name;
private String color;
public Fruit(String name, String color) {
super();
this.name = name;
this.color = color;
System.out.println("name = " + name + ",color = " + color);
}
}
interface FruitInter<F extends Fruit> {
F Fruit(String name, String color);//在接口中定义抽象方法Fruit
}
public class Test {
public static void main(String[] args) {
FruitInter<Fruit> fi = Fruit::new;//引用Fruit类的构造方法,传递给fi
// FruitInter<Fruit> fi = new FruitInter<Fruit>() {
// @Override
// public Fruit Fruit(String name, String color) {
// return new Fruit(name, color);
// }
// };
fi.Fruit("apple", "red");//对fi使用Fruit类的构造方法
//Java编译器自动根据fi.Fruit()方法的签名,选择合适的构造函数
}
}
/*
输出
name = apple,color = red
*/
3. 与 Lambda 的比较
- Lambda 表达式:
stream.forEach(e-> System.out.println(e));
; - 方法引用:
stream.forEach(System.out::println);
; - 可见方法引用是 Lambda 的再进一步简化,但是不建议使用,因为实际操作中可读性差,写代码也不方便;
- 方法引用可以和 Lambda 表达式配合使用,使得 Java 类的构造方法看起来紧凑而简洁,没有很多复杂的模板代码。