JAVA学习笔记Ⅲ——面向对象三特性之继承

面向对象三大特性:封装、继承、多态

继承

继承,字面意思就是继续、承接。在人类生活中,后代可以继承父代或者祖先留下来的遗产等,皇权的继承等。因此继承可以在一定程度上让我们一开始就拥有一些东西,同时呢,一个人也只有一个生父。因此在JAVA中,继承的关系也是如此。

继承的概念 继承的好处 结构
继承是类与类的一种关系,是一种包含关系或者说是一种“is a”的关系。
在继承中被继承的类称为父类或者基类,继承而来的类称为子类。
在JAVA中存在一个Object类,这是所有类的父类。
JAVA中的继承属于单继承,只能继承一个父类
1.子类可以拥有父类所有的属性和方法(private修饰属性除外)
2.可以实现代码复用
class 子类 extends 父类
class A extends B{
…}
“属于”关系 与 “单继承”
           
“富二代”,“官二代代码复用
    
       

注:JAVA中的继承是单继承

子类拥有父类的所有属性和方法(非private)实现代码复用

父类Animal.java

package com.template11;

public class Animal {
    public int age;
    public String name;
    public void eat(){
        System.out.println("动物具有吃东西的能力");

    }
}

子类Dog.java

package com.template11;

public class Animal {
    public int age;
    public String name;
    public void eat(){
        System.out.println("动物具有吃东西的能力");

    }
}

初始化Initial.java

package com.template11;

public class Initial {
    public static void main(String[] args){
        //创建dog对象并调用dog属性
        //dog所有属性和方法都是从父类Animal继承而来
        Dog dog = new Dog();
        dog.age = 10;
        dog.name = "Quanhao Guo";

        //调用dog方法
        dog.eat();

        System.out.println(dog.age);
        System.out.println(dog.name);
    }
}
动物具有吃东西的能力
10
Quanhao Guo

方法的重写

方法的重写 继承的初始化顺序
1.如果子类对继承父类的方法不满意,可以重写父类继承的方法,当调用方法时会优先调用子类的方法。
2.定义的方法中在返回值类型方法名参数类型及个数都要与父类继承的方法相同,才叫方法的重写。
3.调用方法时会优先调用子类的方法
初始化父类→初始化子类
执行初始化对象中属性→执行构造方法中的初始化
先执行父类构造方法再执行子类构造方法。先执行属性初始化,再执行构造方法初始化
        

重写调用示例

Animal.java

package com.template11;

public class Animal {
    public int age = 10;
    public String name;
    public void eat() {
        System.out.println("动物具有吃东西的能力");
    }
    public Animal(){
        age = 100;
        System.out.println("Animal类执行了");
    }
}

Dog.java

package com.template11;

public class Dog extends Animal {
    //重写eat()方法
    public void eat(){
        System.out.println("狗具有吃东西的能力");
    }

}
狗具有吃东西的能力
10
Quanhao Guo

初始化顺序示例

Animal.java

package com.template11;

public class Animal {
    public int age = 10;
    public String name;
    public void eat() {
        System.out.println("动物具有吃东西的能力");
    }
    public Animal(){
        age = 100;
        System.out.println("Animal类执行了");
    }
}

Dog.java

package com.template11;

public class Dog extends Animal {
    //重写eat()方法
    public void eat(){
        System.out.println("狗具有吃东西的能力");
    }

    //重写无参构造方法
    public Dog(){
        System.out.println("Dog类执行了");
    }
}

Initial.java

package com.template11;

public class Initial {
    public static void main(String[] args){
        Animal animal = new Animal();
        System.out.println("animal age:" + animal.age);
        //创建dog对象并调用dog属性
        //dog所有属性和方法都是从父类Animal继承而来
        Dog dog = new Dog();
        dog.age = 10;
        dog.name = "Quanhao Guo";

        //调用dog方法
        dog.eat();

        System.out.println(dog.age);
        System.out.println(dog.name);
    }
}

Animal类执行了
animal age:100
Animal类执行了
Dog类执行了
狗具有吃东西的能力
10
Quanhao Guo

JAVA中 final 关键字

final 关键字
使用final关键字做标识符有”最终的“含义
final 可以修饰类、方法、属性和变量
final 修饰类,则该类不允许被继承
final 修饰方法,则该方法不允许被覆盖(重写)
final 修饰属性,则该类的属性不会进行隐式的初始化(类的初始化属性必须有值)或在构造方法中赋值(但只能选其一,因为不能多次赋值)
final 修饰变量,则该变量的值只能赋一次值,即变为常量

使用final关键字修饰后的父类Animal不能被继承示例

Animal.java

package com.template12;

final public class Animal {
    public int age = 10;
    public String name;
    public void eat() {
        System.out.println("动物具有吃东西的能力");
    }
    public Animal(){
        age = 100;
        System.out.println("Animal类执行了");
    }
}

被final修饰的的方法不能被重写示例

Animal.java

package com.template12;

public class Animal {
    public int age = 10;
    public String name;
    final public void eat() {
        System.out.println("动物具有吃东西的能力");
    }
    public Animal(){
        age = 100;
        System.out.println("Animal类执行了");
    }
}

Animal.java

package com.template12;

public class Animal {
    final public int age = 10;
    public String name;
    public void eat() {
        System.out.println("动物具有吃东西的能力");
    }
    public Animal(){
        age = 100;
        System.out.println("Animal类执行了");
    }
}

final修饰的属性如果未被初始化(包括构造函数内也未初始化)系统不会自动帮我们初始化(即不会默认初始化为0)

Animal.java

package com.template12;

public class Animal {
    final public int age;
    public String name;
    public void eat() {
        System.out.println("动物具有吃东西的能力");
    }
    public Animal(){
        System.out.println("Animal类执行了");
    }
}

因此使用final修饰的属性必须初始化,要么在属性初始化,要么在构造函数进行初始化

对于final修饰局部变量(例如在方法中定义),那么局部变量成为一个常量,不允许被修改。

Animal.java

package com.template12;

public class Animal {
    final public int age = 10;
    public String name;
    public void eat() {
        final int constant = 10;//不允许被再次修改
        constant = 100;
        System.out.println("动物具有吃东西的能力");
    }
    public Animal(){
        System.out.println("Animal类执行了");
    }
}

JAVA中 super 关键字

super 关键字
在对象的内部使用,可以代表父类对象
1.访问父类对象的属性 super.age
2.访问父类的方法 super.eat()
子类的构造过程当中必须调用其父类的构造方法
如果子类的构造方法中没有显示调用父类的构造方法,则系统默认调用父类的无参构造方法
如果子类构造方法中既没有显示调用父类的构造方法,而父类又没有无参构造方法,则编译出错
如果子类显示的调用构造方法,必须在子类的构造方法的第一行

Animal.java

package com.template12;

public class Animal {
    public int age = 10;
    public String name;
    public void eat() {
        System.out.println("动物具有吃东西的能力");
    }
    public Animal(){
        System.out.println("Animal类执行了");
    }
}

Dog.java

package com.template12;

public class Dog extends Animal {
    public int age = 20;

    //重写eat()方法
    public void eat(){
        System.out.println("狗具有吃骨头的能力");
    }

    //重写无参构造方法
    public Dog(){
        //这里隐式的调用了父类的构造方法,类似于增加了一行super(),如下
        //super();如果写了这一行那么这一行必须位于首行
        System.out.println("Dog类执行了");
    }
    
    //定义method方法
    public void method(){
        System.out.println("调用父类的eat()方法");
        super.eat();
        System.out.println("调用子类的eat()方法");
        eat();
        System.out.println("调用父类属性age:" + super.age);
        System.out.println("调用子类(本身)属性age:" + age);
    }
}

Initial.java

package com.template12;

public class Initial {
    public static void main(String[] args){
        Animal animal = new Animal();
        System.out.println("animal age:" + animal.age);
        //创建dog对象并调用dog属性
        //dog所有属性和方法都是从父类Animal继承而来
        Dog dog = new Dog();
        dog.name = "Quanhao Guo";
        dog.method();
    }
}
Animal类执行了
animal age:10
Animal类执行了
Dog类执行了
调用父类的eat()方法
动物具有吃东西的能力
调用子类的eat()方法
狗具有吃骨头的能力
调用父类属性age:10
调用子类(本身)属性age:20

JAVA中 object 类

object 类 与 toString()方法

object 类是所有类的父类,如果一个类没有使用extends关键字明确标识继承另外一个类,那么这个类默认继承 Object 类,Object 类中的方法,适合所有子类。在 Object 类里面定义 toString() 方法的时候返回的对象哈希code(对象地址字符串),可以通过重写 toString() 方法表示出对象的属性。

关系示例 toString() 示例
<

Animal.java

package com.template13;

public class Animal extends Object{
    public int age = 10;
    public String name;
    public void eat() {
        System.out.println("动物具有吃东西的能力");
    }
    public Animal(){
        System.out.println("Animal类执行了");
    }
}

Dog.java

package com.template13;

public class Animal extends Object{
    public int age = 10;
    public String name;
    public void eat() {
        System.out.println("动物具有吃东西的能力");
    }
    public Animal(){
        System.out.println("Animal类执行了");
    }
}

Initial.java

package com.template13;

public class Initial {
    public static void main(String[] args){
        Dog dog = new Dog();
        System.out.println(dog);
    }
}
Animal类执行了
Dog类执行了
Dog{age=20}

JAVA中 equals()方法

equals()方法

比较的是对象的引用是否指向同一块内存地址

  

Transport.java

package com.template15;

public class Transport {

    public int seats;
    public int speed;
    public float price;

    public void setSpeed(int speed) {
        this.speed = speed;
    }

    public void setPrice(float price) {
        this.price = price;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Transport transport = (Transport) o;
        return seats == transport.seats &&
                speed == transport.speed &&
                Float.compare(transport.price, price) == 0;
    }


    public Transport(int seats, int speed, float price){
        this.seats = seats;
        setSpeed(speed);
        setPrice(price);


    }
}

Initial.java

package com.template15;

public class Initial {
    public static void main(String[] args){
        Bus bus_1 = new Bus(100, 200, 300);
        Bus bus_2 = new Bus(100, 200, 300);

        System.out.println("bus_1 parameters:");
        System.out.println(bus_1.seats +" " + bus_1.speed + " " + bus_1.price);
        System.out.println("bus_2 parameters:");
        System.out.println(bus_2.seats +" " + bus_2.speed + " " + bus_2.price);
        
        if(bus_1.equals(bus_2)){
            System.out.println("两者相等");
        }
        else{
            System.out.println("两者不等");
        }
    }
}

Bus.java

package com.template15;

public class Bus extends Transport {

    public Bus(int seats, int speed, float price) {
        super(seats, speed, price);
    }
}

bus_1 parameters:
100 200 300.0
bus_2 parameters:
100 200 300.0
两者相等

猜你喜欢

转载自blog.csdn.net/qq_39567427/article/details/107318856