文章

面向对象简介

面向对象简介

OOP的本质:以类的方式组织代码,以对象的防止组织(封装)数据

三大特性

  1. 封装

    • 保护数据、隐藏代码细节、属性私有set/get

    • alt+insert:自动生成get、set方法

  2. 继承

    • java类只有单继承,接口有多继承

    • final修饰后不能被继承

    • ctrl+h显示继承树

    • super

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
//父类
//所有的类都直接或间接继承Object类,ctrl+h查看
class Person {

    protected String name = "wmj";

    public Person() {
        System.out.println("person的无参构造函数");
    }

    public void print() {
        System.out.println("person");
    }
}

//子类
class Student extends Person {

    private String name = "ww";

    public Student() {
        //隐藏代码 调用了父类的无参构造函数

        super();//调用父类的构造器必须放在第一行
        System.out.println("student的无参构造函数执行了");
    }

    public Student(String name) {
        this.name = name;
    }

    public void print() {
        System.out.println("student");
    }

    public void test(String name) {
        System.out.println(name);//hhh
        System.out.println(this.name);///ww
        System.out.println(super.name);//wmj
    }
}

//测试
public class Application {
    public static void main(String[] args) {
        Student student = new Student();
        student.test("hhh");
    }
}
     /*
     person的无参构造函数
     student的无参构造函数执行了
     haha
     ww
     wmj
     */

方法重写(只和非静态方法有关)

  • 方法名必须相同
  • 参数列表必须相同
  • 修饰符:范围可以扩大不可缩小:public>protected>default>private
  • 抛出的异常:范围,可以缩小不能扩大
  • 静态方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class B {
    public static void test() {
        System.out.println("B.test()");
    }
}

class A extends B {
    public static void test() {
        System.out.println("A.test()");
    }
}

public class Application {
    public static void main(String[] args) {

        //方法的调用只和左边的数据类型有关
        A a = new A();
        a.test();//A.test()

        //父类的引用指向了子类
        B b = new A();
        b.test();//B.test()
    }
}
  • 非静态方法
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
class B {
    public void test() {
        System.out.println("B.test()");
    }
}

class A extends B {
    @Override
    public void test() {
        System.out.println("A.test()");
    }
}

public class Application {
    public static void main(String[] args) {

        //方法的调用只和左边的数据类型有关
        A a = new A();
        a.test();//A.test()

        //父类的引用指向了子类
        B b = new A();
        b.test();//A.test()
    }
}
  1. 多态
    • 同一方法可以根据发送对象的不同而采用多种不同的行为方式

    • 多态是方法的多态
    • 父类和子类有联系 类型转换异常:ClassCastException!
    • 存在条件:继承关系、方法要重写、父类引用指向子类对象!
    • static属于类,final在常量池,private方法都不能重写
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
//所有的类都直接或间接继承Object类,ctrl+h查看
class Person {

    public void run() {
        System.out.println("person");
    }
}

class Student extends Person {
    @Override
    public void run() {
        System.out.println("student");
    }

    public void eat() {
        System.out.println("eat");
    }
}

public class Application {
    public static void main(String[] args) {

        //一个对象的实际类型是确定的
        //可以指向的引用类型就不确定了  父类的引用指向子类

        //Student 能调用的方法都是自己的或者继承父类的
        Student s1 = new Student();
        //Person 不能调用子类独有的方法
        Person s2 = new Student();
        Object s3 = new Student();

        s1.run();//student 子类重写了父类的方法,执行子类的方法
        s2.run();//student

        //对象能执行那些方法,主要看左边的类型
        //s2.eat();错
        ((Student) s2).eat();
        s1.eat();
    }
}

instance

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
public class Application {
    public static void main(String[] args) {

        //System.out.println(x instanceof y);能否编译通过取决于是否有父子关系
        //xy是同一级别会编译报错

        //Object > String
        //Object > Person > Teacher
        //Object > Person > Student
        Object object1 = new Student();
        System.out.println(object1 instanceof Student);//true
        System.out.println(object1 instanceof Person);//true
        System.out.println(object1 instanceof Object);//true
        System.out.println(object1 instanceof Teacher);//false
        System.out.println(object1 instanceof String);//false

        Person person = new Student();
        System.out.println(person instanceof Student);//true
        System.out.println(person instanceof Person);//true
        System.out.println(person instanceof Object);//true
        System.out.println(person instanceof Teacher);//false
        //System.out.println(object2 instanceof String);编译报错

        Student student = new Student();
        System.out.println(student instanceof Student);//true
        System.out.println(student instanceof Person);//true
        System.out.println(student instanceof Object);//true
        //System.out.println(student instanceof Teacher);编译报错
        //System.out.println(student instanceof String);编译报错
    }
}
  • ==父转子要强制转换,才能使用子类特有方法==,丢失父类子自己的那个被子类重写的方法

  • 子转父,会丢失子类特有方法

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
//所有的类都直接或间接继承Object类,ctrl+h查看
class Person {

    public void run() {
        System.out.println("person run");
    }
}

class Student extends Person {

    @Override
    public void run() {
        System.out.println("strdent run");
    }

    public void go() {
        System.out.println("go");
    }
}

public class Application {
    public static void main(String[] args) {
        //父转子
        Person student1 = new Student();
        //student1.go();父类不能调用子类独有的方法,转换成子类的类型才行
        ((Student) student1).go();//强制类型转换
        ((Student) student1).run();//strdent run 丢失父类子自己的那个被子类重写的方法

        //子转父
        Student student2 = new Student();
        student2.go();
        Person person = student2;
        //person.go();子类转父类丢失子类特有的方法
    }
}

static

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
 class Student extends Person {
 
     //执行顺序
     //第2.赋初始值
     {
         System.out.println("匿名代码块");
     }
 
     //第1.只执行一次
     static {
         System.out.println("静态代代码块");
     }
 
     //第3.
     public Student() {
         System.out.println("构造函数");
     }
 
     //执行顺序
     //静态代代码块
     //匿名代码块
     //构造函数
 }
    
 // import static java.lang.Math.random;
 // 静态导入包 Math.random -> random
 
 public class Application {
     public static void main(String[] args) {
 
         Student student = new Student();
 
     }
 }

抽象类

1
2
3
4
5
6
7
8
9
10
11
12
13
 public abstract class Action {
 
     //不能new出来,只能靠子类去继承
 
     //让子类去实现抽象方法,除非他的子类也是抽象类
     //抽象方法只能在抽象类里
     public abstract void doSomething();
 
     //可以写普通的方法
     public void fun() {
         System.out.println("ttt");
     }
 }
  • 构造器

    抽象类的构造函数用来初始化抽象类的一些字段,而这一切都在抽象类的派生类实例化之前发生,可以在其内部实现子类必须执行的代码

接口

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
 public interface UserService {
 
     //没有构造方法
     //常量都是public static final
     int AGE = 0;
 
     //接口中定义的方法都是抽象的public
     void add(); // public abstract
 
     void delete();
 
     void update();
 
     void query();
 }
 
 public interface TimeService {
     void timer();
 }
 
 
 //利用接口实现多继承
 public class UserServiceImpl implements UserService, TimeService {
 
     //实现了接口的类必须重写接口中的所有方法
     @Override
     public void delete() {
 
     }
 
     @Override
     public void update() {
 
     }
 
     @Override
     public void query() {
 
     }
 
     @Override
     public void add() {
 
     }
 
     @Override
     public void timer() {
 
     }
 }

内部类

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
class Outer {
    private int id = 10;

    public void out() {
        System.out.println("外部类的方法");
    }

    // 成员内部类:依附外部类而存在
    // 在定义的内部类的构造器是无参构造器,编译器还是会默认添加一个参数,该参数的类型为指向外部类对象的一个引用
    class Inner {
        public void in() {
            System.out.println("内部类的方法");
        }

        public void getID() {
            System.out.println(id);
        }

        // 局部内部类:定义在一个方法或者一个作用域里面的类,访问仅限于方法内或者该作用域内
        public void method() {
            class Inner2 {

            }
        }
    }

    // 静态内部类:不需要依赖于外部类,和类的静态成员属性类似,并且它不能使用外部类的非static成员变量或者方法
    static class Inner2 {

    }
}


public class Application {
    public static void main(String[] args) {

        Outer outer = new Outer();
        Outer.Inner inner = outer.new Inner();

        // 获得外部类的私有属性
        inner.getID();

        new Outer().out();

        // 匿名内部类,不用把实例保存到变量中
        new UserService() {
            @Override
            public void hello() {

            }
        };
    }
}

interface UserService {
    void hello();
}
本文由作者按照 CC BY 4.0 进行授权