Skip to content

Commit cfbc8c4

Browse files
authored
Create JDK8接口规范.md
1 parent d1c564b commit cfbc8c4

File tree

1 file changed

+164
-0
lines changed

1 file changed

+164
-0
lines changed
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
JDK8接口规范
2+
===
3+
在JDK8中引入了lambda表达式,因此出现了函数式接口的概念,为了保持向前兼容性(比如泛型也是为了保持兼容性而失去了在一些别的语言泛型拥有的功能),
4+
Java接口规范发生了一些改变。
5+
---
6+
## 1.JDK8以前的接口规范
7+
- JDK8以前接口可以定义的变量和方法
8+
- 所有变量(Field)不论是否<i>显式</i> 的声明为```public static final```,它实际上都是```public static final```的。
9+
- 所有方法(Method)不论是否<i>显示</i> 的声明为```public abstract```,它实际上都是```public abstract```的。
10+
```java
11+
public interface AInterfaceBeforeJDK8 {
12+
int FIELD = 0;
13+
void simpleMethod();
14+
}
15+
```
16+
以上接口信息反编译以后可以看到字节码信息里Filed是public static final的,而方法是public abstract的,即是你没有显示的去声明它。
17+
```java
18+
{
19+
public static final int FIELD;
20+
descriptor: I
21+
flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL
22+
ConstantValue: int 0
23+
24+
public abstract void simpleMethod();
25+
descriptor: ()V
26+
flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT
27+
}
28+
```
29+
## 2.JDK8之后的接口规范
30+
- JDK8之后接口可以定义的变量和方法
31+
- 变量(Field)仍然必须是 ```java public static final```
32+
- 方法(Method)除了可以是public abstract之外,还可以是public static或者是default(相当于仅public修饰的实例方法)的。
33+
从以上改变不难看出,修改接口的规范主要是为了能在扩展接口时保持向前兼容。
34+
<br>下面是一个JDK8之后的接口例子
35+
```java
36+
public interface AInterfaceInJDK8 {
37+
int simpleFiled = 0;
38+
static int staticField = 1;
39+
40+
public static void main(String[] args) {
41+
}
42+
static void staticMethod(){}
43+
44+
default void defaultMethod(){}
45+
46+
void simpleMethod() throws IOException;
47+
48+
}
49+
```
50+
进行反编译(去除了一些没用信息)
51+
```java
52+
{
53+
public static final int simpleFiled;
54+
flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL
55+
56+
public static final int staticField;
57+
flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL
58+
59+
public static void main(java.lang.String[]);
60+
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
61+
62+
public static void staticMethod();
63+
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
64+
65+
public void defaultMethod();
66+
flags: (0x0001) ACC_PUBLIC
67+
68+
public abstract void simpleMethod() throws java.io.IOException;
69+
flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT
70+
Exceptions:
71+
throws java.io.IOException
72+
}
73+
```
74+
可以看到 default关键字修饰的方法是像实例方法一样定义的,所以我们来定义一个只有default的方法并且实现一下试一试。
75+
```java
76+
interface Default {
77+
default int defaultMethod() {
78+
return 4396;
79+
}
80+
}
81+
82+
public class DefaultMethod implements Default {
83+
public static void main(String[] args) {
84+
DefaultMethod defaultMethod = new DefaultMethod();
85+
System.out.println(defaultMethod.defaultMethod());
86+
//compile error : Non-static method 'defaultMethod()' cannot be referenced from a static context
87+
//! DefaultMethod.defaultMethod();
88+
}
89+
}
90+
```
91+
可以看到default方法确实像实例方法一样,必须有实例对象才能调用,并且子类在实现接口时,可以不用实现default方法,也可以覆盖该方法。
92+
这有点像子类继承父类实例方法。
93+
<br>
94+
接口静态方法就像是类静态方法,唯一的区别是**接口静态方法只能通过接口名调用,而类静态方法既可以通过类名调用也可以通过实例调用**
95+
```java
96+
interface Static {
97+
static int staticMethod() {
98+
return 4396;
99+
}
100+
}
101+
... main(String...args)
102+
//!compile error: Static method may be invoked on containing interface class only
103+
//!aInstanceOfStatic.staticMethod();
104+
...
105+
```
106+
另一个问题是多继承问题,大家知道Java中类是不支持多继承的,但是接口是多继承和多实现(implements后跟多个接口)的,
107+
那么如果一个接口继承另一个接口,两个接口都有同名的default方法会怎么样呢?答案是会像类继承一样覆写(@Override),以下代码在IDE中可以顺利编译
108+
```java
109+
interface Default {
110+
default int defaultMethod() {
111+
return 4396;
112+
}
113+
}
114+
interface Default2 extends Default {
115+
@Override
116+
default int defaultMethod() {
117+
return 9527;
118+
}
119+
}
120+
public class DefaultMethod implements Default,Default2 {
121+
public static void main(String[] args) {
122+
DefaultMethod defaultMethod = new DefaultMethod();
123+
System.out.println(defaultMethod.defaultMethod());
124+
}
125+
}
126+
127+
输出 : 9527
128+
```
129+
出现上面的情况时,会优先找继承树上近的方法,类似于“短路优先”。
130+
<br>
131+
那么如果一个类实现了两个没有继承关系的接口,且这两个接口有同名方法的话会怎么样呢?IDE会要求你重写这个冲突的方法,让你自己选择去执行哪个方法,因为IDE它
132+
还没智能到你不告诉它,它就知道你想执行哪个方法。可以通过```java 接口名.super```指针来访问接口中定义的实例(default)方法。
133+
```java
134+
interface Default {
135+
default int defaultMethod() {
136+
return 4396;
137+
}
138+
}
139+
140+
interface Default2 {
141+
default int defaultMethod() {
142+
return 9527;
143+
}
144+
}
145+
//如果不重写
146+
//compile error : defaults.DefaultMethod inherits unrelated defaults for defaultMethod() from types defaults.Default and defaults.Default2
147+
public class DefaultMethod implements Default,Default2 {
148+
@Override
149+
public int defaultMethod() {
150+
System.out.println(Default.super.defaultMethod());
151+
System.out.println(Default2.super.defaultMethod());
152+
return 996;
153+
}
154+
public static void main(String[] args) {
155+
DefaultMethod defaultMethod = new DefaultMethod();
156+
System.out.println(defaultMethod.defaultMethod());
157+
}
158+
}
159+
160+
运行输出 :
161+
4396
162+
9527
163+
996
164+
```

0 commit comments

Comments
 (0)