多态概述(polymorphism)
多态: 指的是同一个方法调用,由于对象不同可能会有不同的行为。
现实生活中,同一个方法,具体实现会完全不同。比如:同样是调用人的 休息
方法,张三是睡觉,李四是旅游,数学教授是做数学题;同样是调用人 吃饭
的方法,中国人用筷子吃饭,英国人用刀叉吃饭,印度人用手吃饭。
多态的要点:
多态是方法的多态,不是属性的多态(多态与属性无关)
多态的存在要有3个必要条件:有继承/实现关系,有方法重写,父类引用指向子类对象
父类引用指向子类对象后,用该父类引用调用子类重写的方法,此时多态就出现了
之所以每类人的吃饭方法都不一样,是因为,在人这个类的下边,中国人子类,美国人子类,印度人子类都对吃这个方法进行了重写,所以每类人的吃饭方法不一样。多态是指方法的多态也是因为这样。
多态中成员访问特点
(图1
)
多态中,成员变量的访问特点
System.out.println(a.weight);
编译的时候看的是左边,看的是父类中有没有,如果父类中有,不会报错,如果父类中没有,就会报错
成员变量,编译看左边,运行也看左边
成员方法的访问特点
成员方法编译的时候看的也是左边,看的是父类中有没有,如果父类中有,不会报错,如果父类中没有,就会报错
成员方法,编译看左边,运行看右边
为什么成员变量和成员方法的访问不一样呢?
因为成员方法有重写,而成员变量没有
多态的好处和弊端
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public class Animal {
public void eat () {
System . out . printun ( "动物吃东西" );
}
}
public class Cat extends Animal {
@Override
public void eat (){
System . out . println ( "猫吃鱼" );
}
}
public class Dog extends Animal {
@Override
public void eat () {
System . out . println ( "狗吃骨头" );
}
}
//动物操作类
public class AnimalOperator {
public void useAnimal ( Cat c ) {
c . eat ();
}
public void useAnimal ( Dog d ) {
d . eat ();
}
}
public class AnimalDemo {
public static void main ( string [] args ) {
//创建动物操作类的对象,调用方法
AnimalOperator ao = new AnimalOperator ();
Cat c = new Cat ();
ao . useAnimal ( c ); //猫吃鱼
Dog d = new Dog ();
ao . useAnimal ( d ); //狗吃骨头
}
}
用多态进行简化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
public class Animal {
public void eat () {
System . out . printun ( "动物吃东西" );
}
}
public class Cat extends Animal {
@Override
public void eat () {
System . out . println ( "猫吃鱼" );
}
}
public class Dog extends Animal {
@Override
public void eat () {
System . out . println ( "狗吃骨头" );
}
public void LookDoor () {
System . oUt . println ( "狗看门" );
}
}
//动物操作类
public class AnimalOperator {
public void useAnimal ( Animal a ) { //Animal a = new Cat(); Animal a = new Dog();
a . eat ();
//a.LookDoor(); //编译看左边, Animal中没有LookDoor()方法, 报错
}
}
public class AnimalDemo {
public static void main ( string [] args ) {
//创建动物操作类的对象,调用方法
AnimalOperator ao = new AnimalOperator ();
Cat c = new Cat ();
ao . useAnimal ( c ); //猫吃鱼
Dog d = new Dog ();
ao . useAnimal ( d ); //狗吃骨头
}
}
多态的好处:提高了程序的扩展性,具体体现: 定义方法的时候,使用父类型作为参数,将来在使用的时候,使用具体的子类型参与操作
多态的弊端:不能使用子类的特有功能 (比如:某个方法只有子类有,父类没有,如果要使用,编译看左边,父类中没有,编译不通过,无法使用)
多态中的转型
为什么要学习多态的转型?
多态的弊端是不能使用子类的特有功能,而通过转型,我们就可以使用子类的特有功能
向上转型
向下转型
父类引用指向子类对象,我们称这个过程为向上转型,属于自动类型转换
向上转型后的父类引用变量只能调用它编译类型的方法,不能调用它运行时类型的方法。这时,我们就需要进行类型的强制转换,我们称之为向下转型
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public class Animal {
public void eat () {
System . out . println ( "动物吃东西" );
}
}
public class Cat extends Animal {
@Override
public void eat () {
System . out . println ( "猫吃鱼" );
}
public void playGame () {
System . out . println ( "猫捉迷藏" );
}
}
public class AnimalDemo {
public static void main ( string [] args ) {
//向上转型
Animal a = new Cat ();
a . eat ();
//a.playGame(); 报错
//我现在想使用playGame()怎么办
//①创建Cat对象
Cat c = new Cat ();
c . eat ();
c . playGame ();
//②向下转型
Cat c = ( Cat ) a ; //父类引用转为子类对象
c . eat ();
c . playGame ();
}
}
多态转型内存图解
(图2
)
(图3
)
(图4
)
为了防止在向下转型时,出现类型转换异常,在向下转型中使用 instanceof
,加入 instanceof
进行判断
instanceof
是二元运算符,左边是对象,右边是类;当左边对象是右面的类或右面子类所创建的对象时,返回 true
;否则,返回 false
。
案例(猫和狗多态版)
需求:请采用多态的思想实现猫和狗的案例,并在测试类中进行测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
public class Animal {
private String name ;
private int age ;
public Animal () {
}
public Animal ( String name , int age ) {
this . name name ;
this . age age ;
}
public void eat () {
System . oUt . println ( "动物吃东西" ) ;
}
//set/get......
}
public class Cat extends Animal {
public cat (){
}
public Cat ( String name , int age ) {
super ( name , age );
}
@Override
public void eat () {
System . out . println ( "猫吃鱼" );
}
}
public class Dog extends Animal {
public Dog (){
}
public Dog ( String name , int age ) {
super ( name , age );
}
@Override
public void eat (){
System . out . println ( "狗吃骨头" );
}
}
public class AnimalDemo {
public static void main ( String [] args ) {
//按照多态的方式创建对象并进行测试
Animal a = new Cat ();
a . setName ( "加菲" );
a . setAge ( 5 );
System . out . println ( a . getName () + "," + a . getAge ());
a . eat ();
a = new Cat ( "加菲" , 5 );
System . out . println ( a . getName () + "," + a . getAge ());
a . eat ();
}
}
抽象类概述
在 java
中,一个没有方法体的方法应该定义为抽象方法,而类中如果有抽象方法,该类必须定义为抽象类
1
2
3
public abstract class Animal {
public abstract void eat ();
}
抽象类特点
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//抽象类
public abstract class Animal {
//抽象方法
public abstract void eat ();
public void sleep () {
System . out . println ( "睡觉" );
}
}
public class Cat extends Animal {
@Override
public void eat () {
System . out . println ( "猫吃鱼" );
}
}
public class AnimalDemo {
public static void main ( String [] args ) {
Animal a = new Cat (); //抽象类多态
a . eat ();
a . sleep (); //sleep()通过继承得到的
}
}
(1) 抽象类和抽象方法必须使用 abstract 关键字修饰
public abstract class 类名{ }
public abstract void eat( );
(2) 抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类
(3) 抽象类不能实例化,即不能用 new
来实例化抽象类(即不能直接用抽象类创建对象)
抽象类如何实例化呢?参照多态的方式,通过子类对象实例化,这叫抽象类多态
(4) 抽象类的子类
要么重写抽象类中的所有抽象方法
要么本身也是抽象类 (如果不将继承的抽象方法重写,那么自己本身也是抽象类)
抽象类通过多态使用
抽象类只能用来被继承
抽象类成员特点
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
//抽象类
public abstract class Animal {
private int age = 20 ;
private final String name = "动物" ;
public Animal () {
}
public Animal ( int age ) {
this . age = age ;
}
public void show () {
age = 40 ;
System . out . println ( age );
//name = "老虎";报错 name是常量不能被修改
System . out . println ( name );
}
public abstract void eat ();
}
public class Cat extends Animal {
@Override
public void eat () {
System . out . println ( "猫吃鱼" );
}
}
public class AnimalDemo {
public static void main ( String [] args ) {
Animal a = new Cat (); //抽象类多态
a . eat ();
a . show (); //通过继承得到的 40 动物
}
}
(1) 成员变量
(2) 构造方法
有构造方法,但是不能实例化
那么,构造方法的作用是什么呢?用于子类访问父类数据的初始化
(3) 成员方法
可以有抽象方法:限定子类必须完成某些动作
也可以有非抽象方法:提高代码复用性
抽象类可以包含属性,方法,构造方法。但是构造方法不能用来 new
实例,只能用来被子类调用,用于子类访问父类数据的初始化
案例(猫和狗抽像类版)
需求:请采用抽象类的思想实现猫和狗的案例,并在测试类中进行测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public abstract class Animal {
private String name ;
private int age ;
public Animal () {
}
public Animal ( String name , int age ) {
this . name = name ;
this . age = age ;
}
public abstract void eat ();
//set/get......
}
public class Cat extends Animal {
public Cat () {
}
public Cat ( String name , int age ) {
super ( name , age );
}
@Override
public void eat () {
System . out . println ( "猫吃鱼" );
}
}
public class AnimalDemo {
public static void main ( String [] args ) {
//按照多态的方式创建对象并进行测试
Animal a = new Cat ();
a . setName ( "加菲" );
a . setAge ( 5 );
System . out . println ( a . getName () + "," + a . getAge ());
a . eat ();
a = new Cat ( "加菲" , 5 );
System . out . println ( a . getName () + "," + a . getAge ());
a . eat ();
}
}
接口概述
接口就是一种 公共的规范标准 ,只要符合规范标准,大家都可以通用
Java
中的接口更多的体现在 对行为的抽象
接口是类层次的一种结构
public class 类名
Public interface 接口名
父类 → 本质上是具有共同的内容
接口 → 本质上是提供功能(老鼠夹子和猫都具有抓老鼠的功能)
接口就是比 “抽象类” 还 “抽象” 的 “抽象类”,可以更加规范的对子类进行约束。全面地专业地实现了:规范和具体实现的分离 。
从接口的实现者角度看,接口定义了可以向外部提供的服务。
从接口的调用者角度看,接口定义了实现者能提供那些服务。
区别
普通类:具体实现
抽象类:具体实现,规范(抽象方法)
接口:规范!
声明格式 (JDK8以前)
(图5
)
访问修饰符:只能是 public
或 默认
接口名:和类名采用相同命名机制
Extends:接口可以多继承
常量:接口中的属性只能是常量,总是 public static final
修饰。不写也是
方法:接口中的方法只能是:public abstract
。省略的话,也是 public abstract
接口中没有构造方法,因为接口主要是扩展功能的,而没有具体存在,一个类如果没有父类,默认继承自 Object
类,实现类中无参构造方法的 super()
,访问的是 Object
类中的无参构造方法,Public class A implemrnts B{}
相当于 Public class A extends Object implements B{}
技巧
(1) 子类通过 implements
来实现接口中的规范。
(2) 接口不能创建实例,但是可用于声明引用变量类型。
(3) 一个类实现了接口,必须实现接口中所有的方法,并且这些方法只能是 public
的。
(4) JDK1.8
(不含8)之前,接口中只能包含静态常量、抽象方法,不能有普通属性、构造方法、普通方法。
(5) JDK1.8
(含8)后,接口中包含普通的静态方法、默认方法(default)。
接口特点
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public interface Inter {
public abstract void show ();
}
public class InterImpl implments Inter {
@Override
public void show () {
System . out . println ( "show..." );
}
}
public class InterDemo {
public static void main ( String [] args ) {
Inter i = new InterImpl (); //接口的多态
i . show ();
}
}
1
2
public abstract class InterImpl implments Inter {
}
抽象类 InterImpl
可以实现接口,只不过到时候需要提供一个 InterImpl
的子类才能使用。
(1) 接口用关键字 interface
修饰
public interface 接口名
(2) 类实现接口用 implements
表示
public class 类名 implements 接口名
(3) 接口不能实例化
接口如何实例化呢?参照多态的方式,通过实现类对象实例化,这叫接口多态
多态的形式:具体类多态,抽象类多态,接口多态
多态的前提:有继承或者实现关系;有方法重写;有父(类/接口)引用指向(子/实现)类对象
(4) 接口的实现类
要么重写接口中的所有抽象方法
要么是抽象类
接口成员特点
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public interface Inter {
public int num = 10 ;
public final int num2 = 20 ;
public abstract void show ();
}
public class InterDemo {
public static void main ( String [] args ) {
Inter i = new InterImpl ();
System . out . println ( i . num ); //10
System . out . println ( i . num2 ); //20
//i.num = 40; 报错,默认前边加了一个final,被final修饰,不能修改
//i.num2 = 30; 报错,被final修饰,不能修改
}
}
1
2
3
4
5
6
7
8
9
10
11
//public class InterImpl implements Inter{
public class InterImpl extends Object implements Inter {
public InterImpl () {
super ();
}
@Override
public abstract void show () {
System . out . println ( "show..." );
}
}
如果没有父类,则默认继承 Object
,那么类中的构造方法里的 super()
调用的则是 Object
类的构造方法。
(1) 成员变量
只能是常量
默认修饰符:public static final
(2) 构造方法
没有,因为接口主要是扩展功能的,而没有具体存在
一个类如果没有父类,默认继承自 Object
类
(3) 成员方法
只能是抽象方法
默认修饰符:public abstract
类和接口关系
继承关系,只能单继承,但是可以多层继承
实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时实现多个接口
继承关系可以单继承,也可以多继承 (接口之间可以多继承)
1
2
3
4
5
6
7
// 类和接口的关系
public class InterImpl extends Object implements Inter1 , Inter2 , Inter3 {
}
// 接口和接口的关系
public interface Inter3 extends Inter1 , Inter2 {
}
抽象类和接口的区别
(1) 成员区别
抽象类 变量,常量;有构造方法;有抽象方法,也有非抽象方法
接口 常量;抽象方法
(2) 关系区别
类与类 继承,单继承
类与接口 实现,可以单实现,也可以多实现
接口与接口 继承,单继承,多继承
(3) 设计理念区别
抽象类 对类抽象,包括属性、行为
接口 对行为抽象,主要是行为
对设计理念区别进行详细说明
门和警报的例子
门:都有 open()
和 close()
两个动作,这个时候,我们可以分别使用抽象类和接口来定义这个抽象概念
(图6
)
随着科技的发展,现在的门有了报警的功能,现在有两种方案,一种是都放在抽象类中,一种是都放在接口中
(图7
)
如果都放在抽象类中,那么每个门都有报警的功能,这是不太现实的
如果都放在接口中,那么并不是每个东西都有开门、关门的功能,例如: 报警器
开门、关门属于门本身固有的行为,而报警属于延伸的行为
(图8
)
抽象类是对事物的抽象,例如门
接口是对行为的抽象,例如警报
案例(木门和电动报警门综合案例)
需求:请采用面向对象的思想实现木门和电动报警门的案例,并在测试类中进行测试
(图9
)
(图10
)
分析
①木门
②电动报警门:
成员变量:宽,高,品牌
成员方法:开门,关门,报警
思路
①定义报警(Alarm)接口
②定义门(Door)抽象类
成员变量:宽,高,品牌
构造方法:无参,带参
成员方法:gt/set方法,开门,关门
③定义木门类(WoodDoor),继承门类
④定义电动报警门类(ElectricAlarmDoor),继承门类,实现报警接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/*
报警接口
*/
public interface Alarm {
void alarm ();
}
/*
抽象门类
*/
public abstract class Door {
//宽
private double width ;
//高
private double height ;
//品牌
private String brand ;
//开门
public abstract void open ();
//关门
public abstract void close ();
public Door () {
}
public Door ( double width , double height , String brand ) {
this . width = width ;
this . height = height ;
this . brand = brand ;
}
//set/get......
}
/*
木门
*/
public class WoodDoor extends Door {
@Override
public void open () {
System . out . println ( "手动开门" ) ;
}
@Override
public void close () {
System . out . println ( "手动关门" ) ;
}
public WoodDoor () {
}
public WoodDoor ( double width , double height , String brand ) {
super ( width , height , brand );
}
}
/*
电动报警门
*/
public class ElectricAlarmDoor extends Door implents Alarm {
public ElectricAlarmDoor () {
}
public ElectricAlarmDoor ( double width , double height , String brand ) {
super ( width , height , brand );
}
@Override
public void alarm () {
System . out . println ( "具有报警功能" ) ;
}
@Override
public void open () {
System . oUt . println ( "自动开门" ) ;
}
@Override
public void close () {
System . oUt . println ( "自动关门" ) ;
}
}
/*
测试类
*/
public class DoorDemo {
public static void main ( String [] args ) {
//木门
WoodDoor wd = new WoodDoor ();
wd . open ();
wd . close ();
//wd.alarm(); 报错,没有这个功能
//电动报警门
ElectricAlarmDoor ed = new ElectricAlarmDoor ();
ed . open ();
ed . close ();
ed . alarm ();
//多态
Door d = new WoodDoor ();
d . open ();
d . close ();
d = new ElectricAlarmDoor ();
d . open ();
d . close ();
//d.alarm(); 报错,因为门这个抽象类里没有报警的方法
Alarm a = new ElectricAlarmDoor ();
//a.open(); 报错,因为报警的接口中没有开门和关门的方法
//a.close(); 报错,因为报警的接口中没有开门和关门的方法
a . alarm ();
}
}
JD8 以后接口中新增的方法
接口的组成
常量:public static final
抽象方法:public abstract
默认方法 (Java 8)
静态方法 (Java 8)
私有方法 (Java 9)
默认方法
接口中默认方法的定义格式
概述:JDK8 之后才出现的方法,实现类可以重写,也可以不重写
格式:public default 返回值类型 方法名 (参数列表) {方法体}
范例:public default void show1( ) {方法体}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public interface Inter {
public default void show1 () {
System . out . println ( "默认方法被调用" ) ;
}
}
public class InterImpl implements Inter {
}
public class InterDemo {
public static void main ( String [] args ) {
Inter i = new InterImpl ();
i . show1 ();
}
}
接口中默认方法的 注意事项 :Public
可以省略,default
不能省略
静态方法
接口中静态方法的定义格式
概述:JDK8 之后才出现的方法,只能通过 接口名.方法名()
调用
格式:public static 返回值类型 方法名 (参数列表){方法体}
范例:public static void show2( ){方法体}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public interface Inter {
public static void show2 () {
System . out . println ( "静态方法被调用" ) ;
}
}
public class InterImpl implements Inter {
}
public class InterDemo {
public static void main ( String [] args ) {
Inter i = new InterImpl ();
//i.show2(); 报错,不能通过对象.方法名调用
//InterImpl.show2(); 报错,不能通过实现类.方法名调用
Inter . show2 ();
}
}
接口中静态方法的 注意事项 :
静态方法只能通过接口调用,不能通过实现类名或者对象名调用
Public
可以省略,static
不能省略
私有方法
私有方法 (就是为了给接口中的默认方法和静态方法使用的,外界是不能访问的)
概述:JDK9 之后才出现的方法
接口中私有方法的定义格式
格式1:private 返回值类型 方法名 (参数列表){ 方法体}
范例1:private void show3( ){ }
格式2:private static 返回值类型 方法名 (参数列表){ 方法体}
范例2:private static void show4( ){ }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public interface Inter {
//默认方法
public default void show1 () {
System . out . println ( "默认方法被调用" );
show3 ();
show4 ();
}
//静态方法
public static void show2 () {
System . out . println ( "静态方法被调用" ) ;
//show3(); 报错,静态的方法只能访问静态的方法
show4 ();
}
//私有方法
private void show3 () {
System . out . println ( "私有方法" ) ;
}
//静态私有方法
private static void show4 () {
System . out . println ( "静态私有方法" ) ;
}
}
public class InterImpl implements Inter {
}
public class InterDemo {
public static void main ( String [] args ) {
Inter i = new InterImpl ();
//i.show3(); 报错,因为私有方法在外界是不能访问的
//i.show4(); 报错,因为私有方法在外界是不能访问的
}
}
接口中私有方法的 注意事项 :
默认方法可以调用 私有 的静态方法和非静态方法
静态方法只能调用私有的静态方法
函数式接口概念
函数式接口(Functional Interface
)就是一个 有且仅有一个抽象方法,但是可以有多个非抽象方法
的接口。注解 @FunctionalInterface
可以检测接口是否是一个函数式接口。(在合作开发中,避免同事修改此接口造成错误)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/*
函数式接口
1.interface接口,其次有且只能有一个待实现的抽象方法,允许有default默认方法的存在
2.@FunctionalInterface 编译期检测是否符合函数式接口的规范,类似于@Override
3.建议加上注解@FunctionalInterface, 以避免同事接口改造升级,而带来的简化出现问题
*/
@FunctionalInterface
interface MyFunctionalInterfacel {
void test ();
//void a();
default void b (){};
}
-----------------------------------------
class Test {
public void method ( MyFunctionalInterfacel my ) {
my . test ();
}
}
-----------------------------------------
public class FunctionalDemo1 {
public static void main ( String [] args ) {
Test test = new Test ();
test . method (() -> System . out . println ( "Hello!" )); //匿名内部类,重写MyFunctionalInterfacel中的抽象方法
}
}
函数定义及使用
定义一个函数式接口:
1
2
3
4
5
//问候
@FunctionalInterface
public interface GreetingService {
void sayMessage ();
}
定义此函数式接口的实现类:
1
2
3
4
5
6
7
public class GreetingServiceImpl implements GreetingService {
@Override
public void sayMessage () {
System . out . println ( "say hello!" );
}
}
函数式接口一般作为方法的参数和返回值类型:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Demo {
//定义一个方法,参数使用函数式接口GreetingService
public static void show ( GreetingService greetingService ) {
greetingService . sayMessage ();
}
public static void main ( String [] args ) {
//调用show方法,方法的参数是一个接口,所以可以传递接口的实现类
show ( new GreetingServiceImpl ());
//调用show方法,方法的参数是一个接口,所以可以传递接口的匿名内都类
show ( new GreetingService (){
@Override
public void sayMessage (){
System . out . println ( "使用匿名内类重写接口中的抽象方法" );
}
});
}
}
Lambda+functionInterface
Lambda
+ functionInterface
: 具有延迟加载的效果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
/*
通过lambda + Functional Interface的好处?
1.简化代码,使代码更加简洁
2.延迟加载效果
需求:日志记录(时间+异常类型+异常信息行数) 日志级别达到3才需要记录输出
*/
@FunctionalInterface
interface MyFunctionalInterface2 {
//记录日志的操作
void test ();
}
----------------------------------------
public class FunctionalDemo2 {
/**
* 日志记录器
* @param leveL 日志级别
* @param msg 日志信息
*/
public static void testLog ( int level , string msg ){
if ( level == 3 ){
System . out . println ( msg );
}
}
/**
* 带有函数式接口FunctionalInterface的,日志记录器
* @param leveL 日志级别
* @param my
*/
public static void testLogAndFunctionalInterface ( int level , MyFunctionalInterface2 my ){
if ( level == 3 ){
my . test ();
}
}
public static void main ( string [] args ){
//日志记录(时间+异常类型+异常信息行数)
LocalDateTime now = LocalDateTime . now ();
String type = "NullPointerException" ;
String line = "Bank.java 112" ;
//无论是否符合日志等级,都将会先拼接好日志信息
testLog ( 1 , now + "," + type + "," + line );
//等级一旦不符合,不会进行日志信息的拼接操作
testLogAndFunctionalInterface ( 2 , () -> System . out . println ( now + "," + type + "," + line ));
}
}