ZB-013-java多态

什么是多态

  • 实例方法默认是多态的
    • 在运行时根据this来决定调用那个方法
    • 静态方法没有多态
    • 参数静态绑定,接受者动态绑定
      1. 多态只对方法的接受者生效
      2. 多态只选择接受者的类型,不选择参数的类型
  • 例子:多态
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
public class Main {
public static void main(String[] args) {
// 多态 obj调用print方法 会走进 Sub
Base obj = new Sub();
// 多态 子类对象 SubParam的实例 可以 赋值给 父类引用
BaseParam baseParam = new SubParam();

obj.print(baseParam); // 由于是子类对象,所以会调用 子类的 print方法
// 参数的类型 存在 父子关系,是否会发生多态调用?
// 不会 , 参数是 类型最匹配优先,所以 会按"声明"的时候的定义传递进去
}
}

class Base {
public void print(BaseParam baseParam){
System.out.println("I'm base, print baseParam");
}
public void print(SubParam subParam){
System.out.println("I'm base, print subParam");
}
}

class Sub extends Base{
@Override
public void print(BaseParam baseParam){
System.out.println("I'm sub, print baseParam");
}
@Override
public void print(SubParam subParam){
System.out.println("I'm sub, print subParam");
}
}
class BaseParam {}
class SubParam extends BaseParam{}
  • 例子
    1. shape
    2. HashSet.addAll()
      1
      2
      3
      4
      5
      1 HashSet自己没有 addAll ,从父类继承来的,
      2 调用addAll 会调用 add 方法
      3 而 HashSet 和 父类 都有 add 方法,那么会调用谁的呢?
      4 默念口诀: 实例方法默认是多态的,多态的意思是根据当前的类型来决定调用那个方法
      5 虽然 addAll 在父类中 但当前对象是 HashSet 的实例。所有会调用 HashSet 的 add

相关例子

  • https://github.com/hcsp/shape-polymorphism
  • https://github.com/hcsp/polymorphism-overload-method-selection
  • 策略模式,打折策略
    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
    public static int calculatePrice(String discountStrategy, int price, User user) {
    switch (discountStrategy) {
    case "NoDiscount":
    return price;
    case "Discount95":
    return (int) (price * 0.95);
    case "OnlyVip":
    {
    if (user.isVip()) {
    return (int) (price * 0.95);
    } else {
    return price;
    }
    }
    default:
    throw new IllegalStateException("Should not be here!");
    }
    }

    // 这样的缺点是 后来又多了 N种策略怎么办,别人都不敢轻易改代码了
    把每个策略抽象成一种类型单独维护
    public static int calculatePrice(DiscountStrategy strategy, int price, User user) {
    return strategy.discount(price, user);
    }

    // DiscountStrategy 是父类
    public class DiscountStrategy {
    public int discount(int price, User user) {
    throw new UnsupportedOperationException();
    }
    }
    // 使用 多态实现不同策略
    public class Discount95Strategy extends DiscountStrategy{
    @Override
    public int discount(int price, User user) {
    return (int)(price*0.95);
    }
    }

    public class NoDiscountStrategy extends DiscountStrategy{
    @Override
    public int discount(int price, User user) {
    return price;
    }
    }

    public class OnlyVipDiscountStrategy extends DiscountStrategy{
    @Override
    public int discount(int price, User user) {
    if(user.isVip()){
    return (int)(price*0.95);
    }else{
    return price;
    }
    }
    }
    // 这样每次增加策略就新建一个类就行了。

    // 这是个优点,也是个缺点。是因为 如果10000个策略就10000个类

    // 这样运用“多态”后,“业务和策略”就分离了

涉及金额绝对不能用double

  1. 所有金额乘以 100 (1元= 100分),int去处理
  2. BigDecimal类型 任意精度10进制数

ThreadPoolExecutor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
TheadPoolExecutor(
int corePoolSize,
int maxiumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockKingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler){
...
}


)

// 最后一个参数的意思
RejectedExecutionHandler 就是策略模式在线程池中的应用

做菜实例