我们在使用lambda时,如果方法体中只有一个方法的调用的话(包括构造方法),我们可以用方法引用进一步简化代码。
6.1 推荐用法
我们在使用lambda时不需要考虑什么时候用方法引用,用哪种方法引用,方法引用的格式是什么。我们只需要在写完lambda方法发现方法体只有一行代码,并且是方法的调用时使用快捷键(Alt + Enter)尝试是否能够转换成方法引用即可。
当我们方法引用使用的多了慢慢的也可以直接写出方法引用。
6.2 基本格式
类名或者对象名::方法名
6.3 语法详解(了解)
6.3.1 引用类的静态方法
其实就是引用类的静态方法
格式
类名::方法名
使用前提
如果我们在重写方法的时候,方法体中只有一行代码,并且这行代码是调用了某个类的静态方法,并且我们把要重写的抽象方法中所有的参数都按照顺序传入了这个静态方法中,这个时候我们就可以引用类的静态方法。
在Java中,静态方法是一种属于类而不是实例的方法。可以通过类名调用静态方法,而不需要创建类的实例。静态方法通常用于执行与类相关的任务,而不涉及特定实例的状态。
以下是一个简单的示例,展示了如何定义和使用类的静态方法:
public class MathUtils {
// 静态方法:计算两个数的和
public static int add(int a, int b) {
return a + b;
}
// 静态方法:计算两个数的差
public static int subtract(int a, int b) {
return a - b;
}
public static void main(String[] args) {
// 调用静态方法,无需创建 MathUtils 的实例
int sum = MathUtils.add(5, 3);
int difference = MathUtils.subtract(10, 7);
System.out.println("Sum: " + sum); // 输出: Sum: 8
System.out.println("Difference: " + difference); // 输出: Difference: 3
}
}
在上述例子中,add
和subtract
方法都是静态方法。它们不依赖于类的实例,而是直接通过类名调用。在main
方法中,我们调用了这些静态方法,无需创建MathUtils
的实例。
静态方法的特点:
- 使用
static
关键字声明。 - 可以直接通过类名调用,无需创建类的实例。
- 不能访问类的非静态成员,因为它们不依赖于任何特定的实例。
- 静态方法通常用于执行与类本身相关的任务,而不涉及特定实例的状态。
静态方法还可以在其他静态方法中调用,也可以在非静态方法中调用,但在非静态方法中调用静态方法时,需要使用类名或通过实例对象来调用。
如下代码就可以用方法引用进行简化
List<Author> authors = getAuthors();
Stream<Author> authorStream = authors.stream();
authorStream.map(author -> author.getAge())
.map(age->String.valueOf(age));
注意,如果我们所重写的方法是没有参数的,调用的方法也是没有参数的也相当于符合以上规则。
优化后如下:
List<Author> authors = getAuthors();
Stream<Author> authorStream = authors.stream();
authorStream.map(author -> author.getAge())
.map(String::valueOf);
//--------------------------------------------------------------------------------------------------------------------
6.3.2 引用对象的实例方法
在Java中,实例方法是属于类的实例的方法。与静态方法不同,实例方法需要在类的实例上调用,因此在调用实例方法之前,需要先创建类的实例。
以下是一个简单的示例,展示了如何定义和使用实例方法:
public class Car {
// 实例变量
private String model;
// 构造方法
public Car(String model) {
this.model = model;
}
// 实例方法:获取汽车型号
public String getModel() {
return model;
}
// 实例方法:启动汽车
public void start() {
System.out.println("The car is starting.");
}
public static void main(String[] args) {
// 创建 Car 类的实例
Car myCar = new Car("Toyota");
// 调用实例方法
String carModel = myCar.getModel();
System.out.println("Car Model: " + carModel); // 输出: Car Model: Toyota
myCar.start(); // 输出: The car is starting.
}
}
在上述例子中,getModel
和start
方法都是实例方法。getModel
方法返回汽车的型号,而start
方法打印一条消息表示汽车正在启动。这些方法在类的实例上调用,因此需要先创建一个Car
的实例。
实例方法的特点:
- 不使用
static
关键字声明。 - 必须在类的实例上调用,而不是直接通过类名调用。
- 可以访问和修改实例变量。
- 实例方法通常用于执行与实例相关的任务,涉及特定实例的状态。
在类中,实例方法可以通过 this
关键字引用当前实例。这使得在方法中可以轻松访问实例变量和其他实例方法。
格式
对象名::方法名
使用前提
如果我们在重写方法的时候,方法体中只有一行代码,并且这行代码是调用了某个对象的成员方法,并且我们把要重写的抽象方法中所有的参数都按照顺序传入了这个成员方法中,这个时候我们就可以引用对象的实例方法
例如:
List<Author> authors = getAuthors();
Stream<Author> authorStream = authors.stream();
StringBuilder sb = new StringBuilder();
authorStream.map(author -> author.getName())
.forEach(name->sb.append(name));
优化后:
List<Author> authors = getAuthors();
Stream<Author> authorStream = authors.stream();
StringBuilder sb = new StringBuilder();
authorStream.map(author -> author.getName())
.forEach(sb::append);
实例方法和静态方法有什么区别?
实例方法和静态方法是在Java中两种不同类型的方法,它们有一些重要的区别:
-
关联对象:
- 实例方法: 需要在类的实例上调用,因此与类的特定对象关联。实例方法可以访问和修改实例变量,因为它们在特定对象上执行。
- 静态方法: 与类关联,而不是与特定实例关联。静态方法不能直接访问实例变量,因为它们在没有特定对象的情况下执行。
-
调用方式:
- 实例方法: 必须通过类的实例调用,例如
object.method()
。 - 静态方法: 可以直接通过类名调用,例如
ClassName.method()
。
- 实例方法: 必须通过类的实例调用,例如
-
this 关键字:
- 实例方法: 可以使用
this
关键字引用当前实例,以访问实例变量或调用其他实例方法。 - 静态方法: 不能使用
this
关键字,因为它们没有与特定实例相关联。
- 实例方法: 可以使用
-
访问权限:
- 实例方法: 可以访问实例的成员,包括实例变量和其他实例方法,具有更直接的访问实例状态的能力。
- 静态方法: 不能直接访问实例的成员,只能访问静态成员和其他静态方法。
-
用途:
- 实例方法: 通常用于执行与特定实例相关的任务,可以使用实例状态。
- 静态方法: 通常用于执行与类本身相关的任务,不依赖于特定实例的状态。
示例代码中,前面提到的 getModel
和 start
方法是实例方法,而 add
方法是静态方法。在使用时,需要了解方法的类型并根据具体情况选择调用实例方法或静态方法。
6.3.4 引用类的实例方法
格式
类名::方法名
使用前提
如果我们在重写方法的时候,方法体中只有一行代码,并且这行代码是调用了第一个参数的成员方法,并且我们把要重写的抽象方法中剩余的所有的参数都按照顺序传入了这个成员方法中,这个时候我们就可以引用类的实例方法。
例如:
interface UseString{
String use(String str,int start,int length);
}
public static String subAuthorName(String str, UseString useString){
int start = 0;
int length = 1;
return useString.use(str,start,length);
}
public static void main(String[] args) {
subAuthorName("三更草堂", new UseString() {
@Override
public String use(String str, int start, int length) {
return str.substring(start,length);
}
});
}
优化后如下:
public static void main(String[] args) {
subAuthorName("三更草堂", String::substring);
}
6.3.5 构造器引用
如果方法体中的一行代码是构造器的话就可以使用构造器引用。
格式
类名::new
使用前提
如果我们在重写方法的时候,方法体中只有一行代码,并且这行代码是调用了某个类的构造方法,并且我们把要重写的抽象方法中的所有的参数都按照顺序传入了这个构造方法中,这个时候我们就可以引用构造器。
例如:
List<Author> authors = getAuthors();
authors.stream()
.map(author -> author.getName())
.map(name->new StringBuilder(name))
.map(sb->sb.append("-三更").toString())
.forEach(str-> System.out.println(str));
优化后:
List<Author> authors = getAuthors();
authors.stream()
.map(author -> author.getName())
.map(StringBuilder::new)
.map(sb->sb.append("-三更").toString())
.forEach(str-> System.out.println(str));