文章目录
- 一、匿名内部类
- 二、Lambda表达式
- 三、方法引用
- 1. 语法格式
- 2. 使用方法
- ① 类型的静态方法引用
- ② 类型的构造方法引用
- ③ 类型的实例方法引用
- ④ 对象的实例方法引用
- 四、匿名内部类、Lambda表达式、方法引用对比分析总结
一、匿名内部类
匿名内部类可以看作是特殊的局部内部类,其本质就是一个继承类(或实现接口)的匿名子类。
匿名内部类是在使用的时候动态的指定方法体的逻辑,无需每次都去创建一个继承类(或实现接口)的子类。编译器会在编译阶段自动生成一个匿名子类。
1. 语法格式
匿名内部类的语法格式:new 接口名|类名(){重写方法}
其中,如果重写方法为非必要的,原则上是可以没有重写方法部分的。
2. 使用方法
① 传统方式
父子类:
public class ParentClass {
public void aa(String str) {
}
public void bb(String str) {
}
}
public class ChildClass extends ParentClass {
@Override
public void aa(String str) {
System.out.println("自定义方法体");
}
@Override
public void bb(String str) {
System.out.println("自定义方法体");
}
}
public class Test {
public static void main(String[] args) {
ParentClass ohj = new ChildClass();
}
}
接口实现类:
public interface ParentInterface {
void aa(String str);
void bb(String str);
}
public class ChildClass implements ParentInterface {
@Override
public void aa(String str) {
System.out.println("自定义方法体");
}
@Override
public void bb(String str) {
System.out.println("自定义方法体");
}
}
public class Test {
public static void main(String[] args) {
ParentInterface ohj = new ChildClass();
}
}
② 匿名内部类方式
父子类:
public class ParentClass {
public void aa(String str) {
}
public void bb(String str) {
}
}
public class Test {
public static void main(String[] args) {
ParentClass obj = new ParentClass() {
@Override
public void aa() {
System.out.println("自定义方法体");
}
@Override
public void bb() {
System.out.println("自定义方法体");
}
};
}
}
接口实现类:
public interface ParentInterface {
void aa(String str);
void bb(String str);
}
public class Test {
public static void main(String[] args) {
ParentInterface obj = new ParentInterface() {
@Override
public void aa() {
System.out.println("自定义方法体");
}
@Override
public void bb() {
System.out.println("自定义方法体");
}
};
}
}
二、Lambda表达式
从Java8开始,引入了Lambda表达式。
对于只有一个抽象方法的接口(函数式接口),可以直接使用Lambda表达式创建它的匿名实现类实例。
- 使用匿名内部类方式定义的内部类:编译之后,会生成一个单独的class字节码文件(外部类名$编号.class);
- 使用Lambda表达式定义的内部类:编译之后,不会生成一个单独的class字节码文件,对应的字节码会在运行的时候动态生成。
1. 语法格式
Lambda表达式的语法格式:(参数列表) -> {方法体}
省略写法:
- 小括号内参数的参数类型可以省略
- 小括号内无参数时,小括号不可省略
- 小括号内只有一个参数时,小括号可以省略
- 小括号内有多个参数时,小括号不可省略
- 大括号内有且只有一行语句时,可以省略
2. 使用方法
public interface ParentInterface {
void aa(String str);
}
① 匿名内部类方式
public class Test {
public static void main(String[] args) {
ParentInterface obj = new ParentInterface() {
@Override
public void aa(String str) {
System.out.println("自定义方法体");
}
};
}
}
② Lambda表达式方式
public class Test {
public static void main(String[] args) {
ParentInterface obj = str -> System.out.println("自定义方法体");
}
}
三、方法引用
方法引用是对Lambda表达式进一步简化,借用其他类的方法体,省去了写方法体的过程。
对于方法体只有一行代码的Lambda表达式(该行代码为调用某个类或某个实例的方法时),可以简洁为更简单的方法引用的方式。
1. 语法格式
方法引用的语法格式:
语法种类 |
语法格式 |
示例 |
参数对应关系 |
类型的静态方法引用 |
类::静态方法 |
String::valueOf |
抽象方法的参数与静态方法的参数顺序对应 |
类型的构造方法引用 |
类::new |
String::new |
抽象方法的参数与构造方法的参数顺序对应 |
类型的实例方法引用 |
类::实例方法 |
String::replaceAll |
抽象方法的第一个参数为调用引用方法的实例对象
抽象方法的剩余参数与实例方法的参数顺序对应 |
对象的实例方法引用 |
对象::实例方法 |
s::replaceAll |
实例对象s为外部参数
抽象方法的参数与实例方法的参数顺序对应 |
需要注意:
- 当接口的抽象方法无返回值时,方法引用的方法有无返回值都可以;
- 当接口的抽象方法有返回值时,方法引用的方法也必须有返回值,且返回值类型 instanceof 接口的抽象方法返回值类型
2. 使用方法
① 类型的静态方法引用
类型的静态方法引用:类名::静态方法
对应Lambda表达式:(参数1,参数2,…) -> 类名.静态方法(参数1,参数2,…)
@FunctionalInterface
public interface ParentInterface {
String aa(String s);
}
public class Test {
public static void main(String[] args) {
ParentInterface parentInterface1 = String::valueOf;
ParentInterface parentInterface2 = s -> String.valueOf(s);
}
}
② 类型的构造方法引用
类型的构造方法引用:类::new
对应Lambda表达式:(参数1,参数2,…) -> new 类名(参数1,参数2,…)
@FunctionalInterface
public interface ParentInterface {
String aa(String s);
}
public class Test {
public static void main(String[] args) {
ParentInterface parentInterface1 = String::new;
ParentInterface parentInterface2 = s -> new String(s);
}
}
③ 类型的实例方法引用
类型的实例方法引用:类::实例方法
对应Lambda表达式:(参数1,参数2,…) -> 参数1.静态方法(参数2,…)
@FunctionalInterface
public interface ParentInterface {
String aa(String s1, String s2, String s3);
}
public class Test {
public static void main(String[] args) {
ParentInterface parentInterface1 = String::replaceAll;
ParentInterface parentInterface2 = (s1,s2,s3) -> s1.replaceAll(s2,s3);
}
}
④ 对象的实例方法引用
对象的实例方法引用:对象::实例方法
对应Lambda表达式:(参数1,参数2,…) -> 对象.静态方法(参数1,参数2,…)
@FunctionalInterface
public interface ParentInterface {
String aa(String s1, String s2);
}
public class Test {
public static void main(String[] args) {
String s = "";
ParentInterface parentInterface1 = s::replaceAll;
ParentInterface parentInterface2 = (s1,s2) -> s.replaceAll(s1,s2);
}
}
四、匿名内部类、Lambda表达式、方法引用对比分析总结
- Lambda表达式是匿名内部类的简写(匿名内部类为函数式接口的实现的这种)
- 方法引用是Lambda表达式的简写(Lambda表达式的方法体只有一行代码且该行代码方法调用)