hooyantsing's Blog

第六章_接口、lambda表达式与内部类

字数统计: 915阅读时长: 3 min
2020/06/02

第六章 接口、lambda表达式与内部类

6.1.1 接口概念

92a935db6b63e56bd0223f84e958fb2d.png

不同子类之间进行比较的解决方式。

5290d20f3b562fab1b4eae9817d2a8bc.png

6.1.2 接口的特性

eba1ddc43569baeafaded636410ac3b9.png

b1b52a2c0074c6c6fb5bb51ba3365390.png

eaa28d9e1bc60c0c061bb7851028ec94.png

6.1.4 静态方法

同类一样,static修饰将属于类。也就是属于该接口。

b355f9656f9307bf0d591c5ee801c645.png

InterfaceDemo.java

在接口实现方法过程,是不符合接口规范的。

1
2
3
4
5
6
7
8
9
10
public interface InterfaceDemo {
    //接口里的静态方法需要实现。
    static int getInt1() {
        return 0;
    }

    //常规
    int getInt2(); //public int getInt2();
    int INTNUM = 1; //private static final int INTNUM = 1;
}

6.1.5 默认方法

DefaultInterface.java

接口,default修饰的方法,在实现此接口的子类里是可选择实现的。

1
2
3
4
5
6
public interface DefaultInterface {
    int getInt();
    double getDouble();
    //加入default关键字,此方法作为可选。没有该关键字修饰的方法,继承接口后将必须实现方法。
    default byte getByte(){return 0;}
}

DefaultInterfaceDemo.java

1
2
3
4
5
6
7
8
9
10
11
12
13
public class DefaultInterfaceDemo implements DefaultInterface {
    @Override
    public int getInt() {
        return 0;
    }

    @Override
    public double getDouble() {
        return 0;
    }

    //可以不实现getByte()方法。
}

6.1.6 解决默认方法冲突

79619fd8423965eeddb4fb81c5b06546.png

1.超类优先 [类优先原则]

1df2886ee3e62275a7017bea73b29435.png

2.接口冲突

9d7f02ec01bfabeac530189129e61176.png

0c12cb93f4fcdbab74e88a2268cdf68c.png

浅拷贝

8e5d556bdceba68b05ba31f07be2c7d2.png

可以看出,clone方法仅克隆第一层,第一次引用的对象(实际上是原封不动的复制地址)不变。

90f75a221fc47a52328f739528da7425.png

748f55a04ba95803878362409076824b.png

术语:标记接口

1465f56b2621144187b21bbfbca0d020.png

深拷贝的clone方法的例子:

实现Cloneable接口,最好也重写下clone()方法,调用super.clone()就行。

a8eae4bd5b0b8c95c12c3a5b398eca46.png

6.3.2 lambda表达式的语法

1e6cfd3bb3ecc7f9b4988fbce8b17bcc.png

6.3.3 函数式接口

术语:函数式接口

最好把lambda表达式看作是一个函数,而不是一个对象

f190e122434bb30817165612814e74ba.png

P1 1.lambda表达式会用了么

98bedee3f435e3059768a8b6b0aeec6d.png

986c045779027b1310505ca75f75165a.png

6.3.4 方法引用

9a154da4b8a11aebb0116a31f41ad89e.png

6.3.5 构造器引用

49facc3cc13a38f24a31d4aa3338bd31.png

336f8490ffbce891925f5eb9a2bd1a81.png

6.3.6 变量作用域

lambda包含3个部分

  • 参数;
  • 代码块;
  • 自由变量的值,这里指非参数而且不在代码中定义的变量。
1
2
3
4
5
自由变量

参数 -> {
    代码块
}

术语:闭包

13aa46070864a4b2a092525573b6c8a2.png

什么是闭包?

TODO:

f91b442f833a5f623cddf17a1cdbb563.png

lambda表达式所捕获的自由变量必须是个死值,不会被重新赋值或者改变。

b9ad03e8e3efbc5eec693a075a7efe0d.png

5188f9df0b3865484dfcd6608b152dbe.png

6.3.7 处理lambda表达式

[没懂]

6.4.1 使用内部类访问对象状态

内部类可以直接访问到外围类的域。

c9b00e9b9a7344a7c494797c8b272a88.png

源码:

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
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Date;

public class InnerClassTest {
    public static void main(String[] args) {
        TalkingClock clock = new TalkingClock(1000,true);
        clock.start();

        JOptionPane.showMessageDialog(null,"Quit program ?");
        System.exit(0);
    }
}

class TalkingClock{
    private int interval;
    private boolean beep;

    //构造器
    public TalkingClock(int interval,boolean beep){
        this.interval = interval;
        this.beep = beep;
    }

    public void start(){
        ActionListener listener = new TimePrinter();
        Timer t = new Timer(interval,listener);
        t.start();
    }

    public class TimePrinter implements ActionListener{
        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("At the tone,the time is " + new Date());
            if(beep) Toolkit.getDefaultToolkit().beep();
        }
    }
}

6.4.2 内部类的特殊语法规则

aa1c0084975da4a3bda6d9f0d3db8005.png

578b940a0b2ab8915525ac5d24d716e9.png

6.4.3 内部类是否有用、必要和安全

17b16e9ae6eed16f8d753096735e74bc.png

6.4.4 局部内部类

内部类和局部内部类的区别。

内部类,内部类和外部类的方法在同一级。

局部内部类,局部内部类在外部类的方法里面。

563d2da25cc8aebb519e845f285ee1ea.png

6.4.6 匿名内部类

习惯做法是用匿名内部类实现事件监听器其他回调

071ee9afdc38e70839e33acaf7fa9e5e.png

lambda表达式的应用。

b69879ae48002e49b9c06eabb65d6aab.png

技巧:双括号初始化

c0c104b75438157014a9dc5064551181.png

注意:这个技巧是为ArrayList类并入了新的代码块,所以被执行。因此和原生ArrayList再做Class类对比的时候,会失败。

4a940093b9c4be7aa961e9d9e08e7e1b.png

getClass()在静态方法里遇到的问题。

[没懂]

b5e7e95d6d5aff8d88f5e03bc7fb6abd.png

6.5.2 创建代理对象

8c211e43808b6ea98c536851b5407da3.png

1
2
//参数:加载器 接口 处理器
Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),invocationHandler);

代理Proxy详解: 代理 Proxy

6.5.3 代理类的特性

4605d695729640bcf659b149a4ab5ed1.png

a538158d71a29e70e6003f27236b4934.png

ab7616bacb0dc514feedb0a888b8bbbc.png

CATALOG