前言:

推荐免费Java基础入门视频:【狂神说Java】Java零基础学习视频通俗易懂_哔哩哔哩_bilibili

什么时多态

  • 即同一方法可以根据发送对象的不同而采用多种不同的行为方式。
  • 一个对象的实际类型是正确的,但可以指向对象的引用的类型有很多。
  • 多态存在的条件:
    • 有继承关系
    • 子类重写父类方法
    • 父类引用指向子类对象
  • 多态注意:

    • 多态是方法的多态,属性没有多态性。
    • 父类和子类,有联系,强转类型转换异常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
    //student类

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

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

    //person类
    public class Person {
    public void run(){
    System.out.println("run");
    }
    }

    //main
    public static void main(String[] args) {

    //一个对象的实际类型是确定的
    //new Student();
    //new Person();

    //可以只想的引用类型就不确定了

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

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

    s1.eat();
    //s2.eat();
    }

instanceof和类型转换

  • instanceof关系

    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
    //instandeof
    Object object = new Student();
    //能否编译通过主要看X与Y有无父子关系
    // System.out.println(X instanceof Y);

    System.out.println(object instanceof Student);//true
    System.out.println(object instanceof Person);//true
    System.out.println(object instanceof Person);//true
    System.out.println(object instanceof Teacher);//false
    System.out.println(object instanceof String);//false

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

    Student student = new Student();
    System.out.println("=============================");
    System.out.println(student instanceof Student);//true
    System.out.println(student instanceof Person);//true
    System.out.println(student instanceof Person);//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
    public static void main(String[] args) {
    //类型之间的转换 父 子
    //高 低
    Person student = new Student();

    //student将这个对象转换为Student类型,我们就可以使用Student类型

    ((Student)student).go();

    //子类转化为父类,可能丢失自己本来的方法
    Student student1 = new Student();
    student1.go();
    Person perosn = student1;
    }

static关键字详解

  • 匿名代码块

    1
    2
    3
    {
    //匿名代码块
    }
  • 静态代码块,只执行一次

    1
    2
    3
    static{
    //静态代码块,只执行一次
    }
  • 静态导入包:import static java.lang.Math.random;

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
//Student
/static
public class Student {
private static int age;//静态变量
private double score;//非静态变量

public void run(){

}
public static void go(){

}

public static void main(String[]args){
Student sq = new Student();

System.out.println(Student.age);
System.out.println(sq.age);
System.out.println(sq.score);

Student.go();//直接调用静态方法
}
}

//Person
public class Person {
{
//匿名代码块
System.out.println("匿名代码块");
}
static{
//静态代码块,只执行一次
System.out.println("静态代码块");
}
public Person(){
//构造方法
System.out.println("构造方法");
}
public static void main(String[]args){
Person person = new Person();
System.out.println("===========");
Person person1 = new Person();

}
}

//Test类
package com.opp.demo03;
//静态导入包
import static java.lang.Math.random;
import static java.lang.Math.PI;
/**
* @author Joker大雄
* @data 2021/8/15 - 13:28
**/
public class Test {
public static void main(String[] args) {
System.out.println(random());
System.out.println(PI);
}
}

抽象类

  • abstract修饰符可以用来修饰方法也可以修饰类,如果修饰方法,那么该方法就是抽象方法;如果修饰类,那么该类就是抽象类。
  • 抽象类中可以没有抽象方法,但是有抽象方法的类一定要声明为抽象类。
  • 抽象类,不能使用new关键字来创建对象,他是用来让子类继承的。
  • 抽象方法,只有方法的声明,没有方法的实现,它是用来让子类实现的。
  • 子类继承抽象类,那么就必须要实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类。

  • 思考: 抽象方法存在构造器吗?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    //abstact 抽象类  extends 单继承(接口可以多继承)
    public abstract class Action {
    //约束,有人帮我们实现
    public abstract void doSomething();

    // 1. 不能new这个抽象类,只能考子类去实现它:约束。
    // 2. 抽象类中可以写普通方法
    // 3. 抽象方法必须在抽象类中
    //抽象的抽象:约束
    //思考: 抽象方法存在构造器吗?
    }

    //test类
    //抽象类的所有方法,继承了它的子类,都必须要实现它的方法,除非子类也是抽象类
    public class Test extends Action{
    @Override
    public void doSomething() {

    }
    }

接口的定义与实现

  • 普通类:只有具体实现
  • 抽象类:具体实现和规范(抽象方法)都有。
  • 接口:只有规范。
  • 接口就是规范,定义的是一组规则,体现了现实世界中”如果你是…则必须能…”的思想(例如:如果你是车,则必须能跑)

  • 接口的本质是七月,就像人类社会的法律一样。制定好后大家都遵守。

  • OO的精髓,是对对象的抽象,最能体现这一点的就是接口。为什么我们讨论设计模式都只针对具备了抽象能力的语言(如:C++,Java,C#等),就是因为设计模式所研究的,实际上就是如何合理的去抽象。

  • 声明类的关键字是class,声明接口的关键字是interface

  • 接口的作用:

    • 约束
    • 定义一些方法,让不同的人实现
    • public abstract
    • public static final
    • 接口不能被实例化,接口中没有构造方法
    • implements可以实现多个接口
    • 必须要重写接口中方法
    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
    //UserService接口
    public interface UserService {
    //接口中所有对象都是抽象的 修饰符默认public
    //接口中定义的是常量,一般不会这样定义
    void run();
    void delete(String name);
    void update(String age);
    void query(String name);
    }
    //TimeService接口
    public interface TimeService {
    void time();
    }

    //利用接口实现多继承
    public class UserServiceImpl implements UserService,TimeService{
    @Override
    public void run() {

    }

    @Override
    public void delete(String name) {

    }

    @Override
    public void update(String age) {

    }

    @Override
    public void query(String name) {

    }

    @Override
    public void time() {

    }
    }

N种内部类

  • 内部类就是在一个类的内部再定义一个类,比如,A类中定义一个B类,那么B类相对A类来说就称为内部类,而A类相对B类来说就是外部类。
  • 成员内部类

  • 静态内部类

  • 局部内部类

  • 匿名内部类

    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 class Outer {
    private int id;
    public void out(){
    System.out.println("外部类");
    }
    //全员内部类
    public class Inner{
    public void in(){
    System.out.println("内部类");
    }
    //获得外部类的私有属性
    public void getId(){
    System.out.println(id);
    }
    }
    //局部内部类
    public void method(){
    class Inner{
    public void in(){

    }
    }
    }

    public static void main(String[] args) {
    //没有名字初始化类,不用将实例保存到变量中
    //匿名内部类
    new Apple().eat();

    UserService us = new UserService(){
    //重写方法
    @Override
    public void hello() {

    }
    };

    }

    }
    //一个java类中可以有多个class类,但只能有一个public的类
    class A{
    }
    //匿名内部类
    class Apple{
    public void eat(){
    System.out.println("1");
    }
    }
    interface UserService{
    void hello();
    }

    //Application类main方法
    public static void main(String[] args) {

    Outer out = new Outer();
    //通过这个外部类来实例化内部类
    Outer.Inner inner =out.new Inner();
    inner.in();
    }