JAVA04-单例设计模式与组合设计模式

设计模式之单例模式

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
  /**
 * 单例设计模式之饿汉式
 * 1. 私有化构造器
 * 2. 提供实例常量
 * 3. 提供工厂方法getInstance方法返回实例常量
 */
public class World {
    private static final World SINGLETON_INSTANCE = new World();

    public static World getInstance() {
        return SINGLETON_INSTANCE;
    }

    private World() {
    }
}

JAVA03-Builder设计模式和模板模式

设计模式之Builder模式

解决了一个类参数过多,而导致的构造器参数 太长,或构造器太多的问题

 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
  public class Person {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Person(String name) {
        this(name, 19);
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

/**
 * Builder模式
 * 1. 和目标类同样的属性
 * 2. 私有构造器(不是必须)
 * 3. 静态工厂方法(不是必须)
 * 4. 一个属性一个设置方法,该方法返回自身this
 * 5. 通过build方法将收集到的方法都设置到目标类中,并返回目标类
 */
public final class PersonBuilder {
    private int age;
    private String name;

    private PersonBuilder() {
    }

    // 静态工厂方法
    public static PersonBuilder aPerson() {
        return new PersonBuilder();
    }

    public PersonBuilder withAge(int age) {
        this.age = age;
        return this; // Builder模式的要点是返回自己 this
    }

    public PersonBuilder withName(String name) {
        this.name = name;
        return this; // Builder模式的要点是返回自己 this
    }

    // 最后通过build方法将参数设置到Person类中并返回
    public Person build() {
        Person person = new Person(name);
        person.setAge(age);
        return person;
    }
}

JAVA02-面向对象和工厂方法

如果没有任何构造函数,编译器会偷偷帮你生成一个无参数的构造器

重载时,如果一个方法调用可以匹配多个方法声明时,类型最匹配的最优先调用

 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
public class Main {
    // 默认会调用这个方法,因为1这个常量是int类型
    public static void foo(int i) {
        System.out.println(i);
    }

    // 如果注释以上所有的方法,则会调用这个方法,因为int能被自动装箱成Integer
    public static void foo(Integer i) {
        System.out.println(i);
    }

    // 如果注释以上所有的方法,则会调用这个方法,因为Integer继承了Number
    public static void foo(Number i) {
        System.out.println(i);
    }

    // 如果注释以上所有的方法,则会调用这个方法,因为Number继承了Object
    public static void foo(Object i) {
        System.out.println(i);
    }

    public static void foo(List list) {
        System.out.println(i);
    }

    public static void main(String[] args) {
        // 请问以下代码,会调用哪个签名的方法?
        foo(1);

        foo(null); // 这行代码会报错? 为什么? 怎么解决?
        /*
        因为null没有类型,下面的方法和List签名的方法冲突,编译器不知道该调用哪个
        因此你需要告诉编译器到底该调用哪个方法,可以用强制转换来解决
        
        foo((List)null)
        */
        
        /*
        如果把List签名的方法注释掉,程序又不报错了,为什么?
        答:因为根据类型匹配规则,null没有类型,因此int签名的方法被排除,接下来
        考虑对象类型,又因为Integer是Number的子类Number又是Object的子类,
        因此Integer最先匹配,所以它会调用Integer签名的方法
        
        那么为什么加上List签名的方法会编译器会找不到而报错呢?
        答:因为List和Integer都是Object的子类,List和Integer之间不构成父子类型
        它们到Object类之间的距离相同,因此编译器不知道该调用哪个方法
        */
    }
}

JAVA01-避坑

浮点数不能通过 == 进行比较

因为Java中浮点数是一个近似值而不是一个绝对值
应该用两个数的差,的绝对值来判断是否小于一个较小的数

1
2
3
4
5
6
7
  // 判断两个double是否相等
public class Main {
    public static boolean doubleEquals(double a, double b) {
        // 应该用两个数的差,的绝对值来判断是否小于一个较小的数
        return Math.abs(a - b) < 0.0000001;
    }
}