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类之间的距离相同,因此编译器不知道该调用哪个方法
        */
    }
}

对象的初始化顺序

1. 静态成员
2. 静态代码块
3. 实例成员
4. 实例代码块
5. 构造器
6. 在继承体系中,继承链最顶端的先初始化,然后依次向下

Java的访问控制符

1. public 所有人都可以访问
2. protected 子类和同包中的类可以访问
3. package private 包级私有(默认什么修饰符都不写就是包级私有),同包的可以访问
4. private 私有,只有自己可以访问
5. 包级私有是可以被绕过的

设计模式之工厂方法

 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
  public class Person {
    private String name;
    private int age;
    private static final Person INVALID_PERSON = new Person("INVALID Person", 0);

    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;
    }

    /**
     * 私有化构造器
     * @param name 名字
     */
    private Person(String name) {
        this(name, 20);
    }

    /**
     * 私有化构造器
     * @param name 名字
     * @param age 年龄
     */
    private Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    /**
     * 静态工厂方法的好处
     * 1. 名字可以和类名不同,可以通过名字很好的了解函数的意图
     * 2. 静态工厂方法还可以返回一个预先定义好的实例,从而不用每次都new对象
     * 3. 静态工厂方法还可以返回子类对象,而构造器只能返回本类对象
     * @param age 年龄
     * @return 返回对应年龄的张三
     */
    public static Person newZhangSan(int age) {
        if (age < 0 || age > 200) {
            return INVALID_PERSON;
        }
        return new Person("张三", age);
    }
}
updatedupdated2025-03-012025-03-01