继承、重载、重写、多态、抽象类、接口、final、Static

继承、重载、重写、多态、抽象类、接口、final、Static

继承

继承就是子类继承父类的属性和方法,实现代码复用。

在父类里面抽取的属性和方法一定是所有子类所共有

Java是单继承,就是一个类只能继承extends(inherit)一个类,而java这种面向对象的语言就是对现实世界的描述,现实世界中是存在很多多继承,但是java里面是支持实现多个接口。

Object是所有类的父类(这个父类不一定是直接父类)

Java里面new子类对象时候首先把父类对象new出来。

//一个类不继承任何一个类,默认继承Object
public class Person/* extends Object*/{
    //如果希望子类继承 protected
    protected int id;
    protected String name;
    protected int age;

    public Person() {
        //Java里面new子类对象时候首先new父类对象
        super();//new Object();
    }

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

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

//实体类:和数据库表一一对应
public class Student extends Person{
//    private int id;
//    private String name;
//    private int age;
    private String className;

    public Student() {
        super();//new Person();
    }

    public Student(int id, String name, int age, String className) {
x'cxc        super(id, name, age);//new Person(id,name,age)
        this.className = className;
    }

//    public void show() {
//        System.out.println("Student.show");
//    }

    public void study() {
        System.out.println(className + "班的"+name+"正在学习");
    }
}

this、super总结:

1. this:代表当前类的对象 this.id=id
2. super:代表父类对象,在子类里面想调用父类属性或者方法
3. this():调用当前类的其他构造方法
4. super():调用父类构造方法

public class Student extends Person {
    protected  int className;

    public int getClassName() {
        return className;
    }

    public void setClassName(int className) {
        //this 代表本类的对象
        this.className = className;
    }

    public Student() {
        //调用父类的构造方法
        //super();
        //调用本类的构造方法
        this(1,"1",1,"1",1);
        //代表父类的对象
        super.age=className;


        this.className = className;
    }

    public Student(int id, String name, int age, String gender, int className) {
        //调用父类的构造方法
        super(id, name, age, gender);
        this.className = className;
    }
}

不写,Java默认加上:

1. 无参构造方法
2. 一个类不继承任何一个类默认继承extends Object
3. 在类的构造方法第一句默认会加上super()

重载

重载(Overload)是指在同一个类中可以有多个方法拥有相同的名称,但是它们的参数列表不同。

Java通过方法的参数类型、个数或顺序来区分不同的重载方法。

最典型的重载:构造方法重载(无参构造方法、有参构造方法)

方法重载特点:与返回值无关,只看参数列表。

void show(int a, char b, double c){}

1. void show(int x, char y, double z){}   不是重载,是同一个方法
2. int show(int a, double c, char b){}      是重载,参数顺序不一样,和返回值无关
3. void  show(int a, double c, char b){}  是重载,参数顺序不一样
4. boolean show(int c, char b){}          是重载
5. void show(double c){ }                     是重载
6. double show(int x, char y, double z){}  不是重载

重写(覆盖)@Override

父类中定义的方法子类不满意,子类重新定义这个方法,最典型的重写就是toString()

重写的规则:

1. 方法名必须相同
2. 参数列表必须完全相同
3. 返回值类型必须相同(或是其子类)
4. 访问权限不能比父类更严格(可以更宽松)
5. 不能抛出比父类更多的异常

public class Object {
    public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }
}

public class Student {
    @Override
    public String toString() {
        return "Student{" +
                "className='" + className + '\'' +
                ", id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

重写 vs 重载:

重写 Override 重载 Overload
发生在父子类之间 发生在同一个类中
方法名相同,参数相同 方法名相同,参数不同
返回值必须相同 返回值无关

多态

Java 多态(Polymorphism)是面向对象编程的一项核心概念,它允许对象以多种形式出现。

多态性在Java中有两个主要的表现形式:

  1. 编译时多态(也称为静态多态)
  2. 运行时多态(也称为动态多态)

编译时多态是通过方法重载(Method Overloading)实现的。这意味着在同一个类中可以定义多个方法,这些方法具有相同的名字但参数列表不同。编译器在编译时根据参数列表来决定调用哪个具体的方法。

这里大家只要知道多态还有编译时多态这种形式就可以,重点还是运行时多态。

多态存在的三个必要条件:

1. 继承
2. 重写
3. 父类引用指向子类对象 Cal cal = new Add();

// 父类 Animal
public class Animal {
    public void eat() {
        System.out.println("动物吃饭");
    }
}

public class Dog extends Animal {
    @Override
    public void eat() {
        System.out.println("狗啃骨头");
    }
}

public class Cat extends Animal {
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
}

// 测试多态
public class Test {
    public static void main(String[] args) {
        // 父类引用指向子类对象
        Animal a1 = new Dog();
        a1.eat(); // 输出:狗啃骨头,调用子类的方法

        Animal a2 = new Cat();
        a2.eat(); // 输出:猫吃鱼,调用子类的方法
    }
}

抽象方法、抽象类

抽象类和接口都是用来实现抽象,规范子类行为,是面向接口编程的基础。

抽象方法

如果一个方法只有声明,没有实现(没有方法体),那么这个方法就是抽象方法,用 abstract 修饰。

public abstract void eat();

抽象类

包含抽象方法的类必须是抽象类,用 abstract 修饰。

public abstract class Animal {
    // 抽象方法,没有方法体
    public abstract void eat();

    // 抽象类可以有普通成员变量和普通方法
    private String name;

    public String getName() {
        return name;
    }

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

特点:

  • 抽象类不能创建对象,因为抽象方法没有实现,创建对象调用抽象方法没有意义
  • 抽象类必须被子类继承,子类必须重写所有抽象方法,才能创建对象;如果子类没有重写所有抽象方法,子类也必须是抽象类

示例:

public abstract class Animal {
    public abstract void eat();
}

public class Dog extends Animal {
    @Override
    public void eat() {
        // 必须实现抽象方法
        System.out.println("狗吃骨头");
    }
}

// 使用
public class Test {
    public static void main(String[] args) {
        // Animal animal = new Animal(); // 错误,抽象类不能创建对象
        Animal a = new Dog(); // 多态,没问题
        a.eat();
    }
}

如果这个类是抽象类,并不要求这个类一定要有抽象方法

抽象类里面可以有普通方法,也可以有抽象方法。

如果一个类是抽象类,那么这个类就不能被new实例化,只能被其他类继承。

抽象方法可以理解为父类(抽象类)定义的一个模板或者规范(自己本身不实现),子类必须实现这个抽象方法,如果子类不想实现这个方法,那么这个子类也必须要变成抽象类。

接口

接口是一个纯粹的抽象类(接口里面所有的方法都是抽象方法)

接口就是一个规范(标准),他没有提供任何是实现,具体的功能由实现接口的子类去实现。

接口就是一个规范,可插拔(可以被替换,首先定义一个标准(接口),大家都遵守这个标准,就可以实现互相之间替换)

面向接口编程

接口有广义和狭义:

  1. 狭义:就是Java里面接口这个技术 interface
  2. 广义:声明成父类类型,指向不同的子类对象。

这里的父类可以是:接口、抽象类、普通父类

接口也是父类的一种

接口的使用

接口是一种更彻底的抽象,接口中所有方法都是抽象方法(Java 8 之前)。

接口用 interface 关键字定义:

修饰符 interface 接口名 {
    // 常量
    // 抽象方法
}

示例:

// 定义接口
public interface Flyable {
    // 接口中的属性默认是 public static final
    double MAX_SPEED = 1200;

    // 接口中的方法默认是 public abstract
    void fly();
}

类实现接口使用 implements 关键字:

public class Bird implements Flyable {
    @Override
    public void fly() {
        System.out.println("鸟儿用翅膀飞");
    }
}

public class Airplane implements Flyable {
    @Override
    public void fly() {
        System.out.println("飞机用引擎飞");
    }
}

特点:

  • 接口不能创建对象
  • 一个类可以实现多个接口,弥补 Java 单继承的不足
  • 实现类必须重写接口中所有抽象方法,否则实现类也必须是抽象类

final总结:修饰变量、类、方法

1. final变量:这个变量就不能被修改,就是常量 public static final double PI = 3.1415;
2. final类:这个类就不能被继承
3. final方法:这个方法就不能被重写
4. 接口和抽象类不能使用,没有意义

静态属性、静态方法

static void main(String[] args) {
    //Math math = new Math();
    //int max = math.max(3, 5);
    //静态方法调用,不需要new对象,直接: 类名.方法名()
    int max = Math.max(3, 5);
    System.out.println(max);
}

如何理解静态属性、静态方法

小区里面业主的房子可以看成一个一个的对象,这些都是属于特定的业主所独有。但是小区里面也有一些公共设施(健身器材、绿地),这些公共设施是属于这个小区的。但是是可以被所有的业主对象所使用的。

非静态的属性和方法(实例属性和方法)必须通过new对象访问,而静态的属性和方法是属于类的,在类加载到内存中就可以访问,不需要new对象就可以使用,但是可以被所有对象所共享。

使用时候注意点:

1、静态的方法只能访问静态的方法和静态的属性(因为当前对象的实例可以没有创建,所以静态的方法是没办法调用非静态的方法和属性的)

2、静态的方法中不能写this、super关键字(因为当前的对象实例可能还没有创建,代表当前类对象的this还有代表父类对象的super可能都还没有创建)

public class Student {
    //属性、成员变量、实例变量
    public int id;
    private String name;
    //静态变量
    public static String country = "中国";

    //成员方法、实例方法、非静态方法
    public void show() {
        System.out.println("Student.show");
        print();
    }

    //静态方法
    public static void print() {
        System.out.println("Student.print");
        //Non-static method 'show()' cannot be referenced from a static context
        //show();
        //this.name = "lisi";
        country = "zhongguo";
        //this.name = "ss";
    }

    public static void test() {
        test();
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
上一篇
下一篇