Java基础11 面向对象~继承

为热爱编程的你点赞!
学习SpringBoot实战课程 https://edu.csdn.net/course/detail/31433
学习SpringCloud入门课程 https://edu.csdn.net/course/detail/31451


面向对象系列:
类和对象
封装
继承
多态
static关键字和单例模式
接口和内部类

前言

本文我们开始探讨面向对象的另一个重要特征——继承,大家会学习到继承的相关概念、super关键字、继承中的构造方法、final关键字以及抽象方法等。

继承概述

现实中的继承:
在这里插入图片描述
程序中的继承:
可以由子类继承父类的成员(属性和方法),起到代码重用的作用
特点:

  1. 程序中的类分为父类和子类
  2. 子类可以继承父类,也可以说父类派生子类
  3. 子类可以继承父类的属性和方法,是一种代码重用的机制

如何判定两个类具有继承关系呢?
子类和父类具有is a(是一种)关系,子类 is a 父类
狗 is a 动物、汽车 is a 交通工具…

继承的语法

public class 子类 extends 父类{

} 

案例:学生继承人,学生可以继承人类公有的属性和方法,只需要定义自身特有的属性和方法,大大减少了重复代码的编写。

/**
 * 人类
 */
public class Person {

	private String name;
	private int age;
	
	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;
	}
	
	public void eat(){
		System.out.printf("%d的%s在吃东西\n",age,name);
	}
}

/**
 * 学生类
 */
public class Student extends Person{

	//学号
	private String no;

	public String getNo() {
		return no;
	}

	public void setNo(String no) {
		this.no = no;
	}
	
	public Student(){
		
	}
	
	public Student(String no,String name,int age) {
		this.no = no;
		//调用了父类的方法
		this.setName(name);
		this.setAge(age);
	}

	public void study(){
		//调用了父类的方法
		System.out.printf("%d岁的学号%s的%s同学在学习Java",this.getAge(),this.getName(),no);
	}
}

public class StudentDemo {

	public static void main(String[] args) {
		Student stu = new Student("001","张三",20);
		//调用父类方法
		stu.eat();
		//调用自身方法
		stu.study();
	}

}

在这里插入图片描述

Java中的继承的特性

  • 传递性,父类的成员可以传递给子类,以及子类的子类
  • 单根性,子类只能有一个父类

super关键字

super代表父类对象
作用有:

  1. 调用父类的属性
super.属性
  1. 调用父类的方法
super.方法(..)
  1. 调用父类的构造方法
super(参数);

super和this的区别:

  1. this代表当前类的对象,super代表父类的对象
  2. this可以调用当前类的属性和方法(包括自身特有和父类的)
    super只能调用父类的属性和方法
  3. this可以调用自身的构造方法,super可以调用父类的构造方法

super调用父类的构造方法:

给父类添加构造方法:
public Person() {
	System.out.println("这是Person无参的构造方法");
}
public Person(String name, int age) {
	this.name = name;
	this.age = age;
	System.out.println("这是Person带参的构造方法");
}

给子类添加构造方法:
public Student(){
	System.out.println("这是Student无参的构造方法");
}

public Student(String no,String name,int age) {
	//调用了父类的构造方法
	super(name,age);
	this.no = no;
	System.out.println("这是Student带参的构造方法");
}

调用子类:
Student stu = new Student();
Student stu1 = new Student("001","张三",20);

在这里插入图片描述
注意:

  1. 子类如果不写super,系统会默认调用父类无参的构造方法
  2. 调用父类有参构造方法时,子类必须使用super显式的调用父类的构造方法
  3. super()必须出现在子类构造方法的第一行
  4. 构造方法的调用,总是先调用父类的,再调用子类的

方法重写

什么是方法重写?
子类中的方法可以覆盖父类中的方法
方法重写的特点:

  1. 方法在子类和父类中
  2. 方法名相同
  3. 参数、返回值都相同
  4. 子类方法的访问修饰符不能比父类更严格

学生类重写父类的eat方法

//重写父类的方法
public void eat(){
	System.out.printf("%d的%s同学在吃KFC\n",this.getAge(),this.getName());
}

Student stu1 = new Student("001","张三",20);
stu1.eat();

在这里插入图片描述

Object类

Object类是Java中一切类的父类
Object类的常用方法:

  • equals 比较是否相等
  • hashCode 返回哈希代码
  • getClass 返回对象的类型信息
  • toString 返回对象的字符串信息

==和equals的区别
==对于基本类型,比较的是值;
对于引用类型,比较的是内存地址。
Object类的equals比较的也是对象的地址,因为源码中是用==实现的

public boolean equals(Object obj) {
    return (this == obj);
}

对于String类型来说,equals比较的是字符内容,因为String类重写了Object类的equals方法

public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String)anObject;
        int n = value.length;
        if (n == anotherString.value.length) {
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = 0;
            while (n-- != 0) {
                if (v1[i] != v2[i])
                    return false;
                i++;
            }
            return true;
        }
    }
    return false;
}

思考下面代码的执行结果:

String s1 = "abcd";
String s2 = "abcd";
String s3 = new String("abcd");
System.out.println(s1==s2);		
System.out.println(s2==s3);		
System.out.println(s2.equals(s3));	

在这里插入图片描述

对于"abcd"这种常量值,分配在常量池中的;字符串常量是可以反复使用的。
第1、2行代码的“abcd”是同一个常量。
第3行代码使用new,会在堆中创建新的对象。
第4行代码,s1和s2是同一个对象,结果为true
第5行代码,s2和s3不是同一个对象,结果为false
第6行代码,equals比较的是字符串的值,结果为true

final关键字

用于修饰类、变量、方法

  1. 被final修饰的类,不能被继承
final class A{}
class B exends A{} //错误
  1. 被final修饰的变量变成常量,不能修改值
final int num = 2000;
num++; //错误
  1. 被final修饰的方法,不能重写
class A{
	public final void test(){}
}
class B extends A{
	public void test(){} //错误
}

抽象方法和抽象类

在实际开发过程中,有时候我们需要把某些方法的具体实现,推迟到子类中实现。
抽象方法的意义在于:

  1. 可以规范方法的定义(返回值类型、方法名、参数)
  2. 具体实现由子类完成

抽象方法:

public abstract 返回值 方法名(类型 参数);

抽象类

abstract class 类名{

}

修改Person类

/**
 * 抽象类
 */
public abstract class Person {

    ....省略其他代码
    //抽象方法
	public abstract void eat();
}

注意:

  1. 一旦类中定义了一个抽象方法,这个类必须定义成抽象类
  2. 有抽象方法的类,必须是抽象类;抽象类不一定有抽象方法

抽象类的特点

  1. 抽象类不能实例化
  2. 抽象类必须由子类继承并实现其中的抽象方法,除非子类也是抽象的

结束

最后给大家留两个编程题:
1、定义交通工具类,属性:颜色、速度、耗油量;方法:移动、停止。
定义汽车类和轮船类继承交通工具,汽车类有品牌属性,有刹车方法
轮船有排水量属性,有抛锚方法。
创建汽车和轮船对象,并调用所有的方法。
2、定义一个家电类,定义功率、价格、品牌属性,定义启动方法用于输出这些属性。
定义一个电视类,继承家电类,添加播放方法。
创建电视对象,调用播放方法。
最后给家电添加有参的构造方法,在电视中用super调用父类构造方法。


大家如果需要学习其他Java知识点,戳这里 超详细的Java知识点汇总

猜你喜欢

转载自blog.csdn.net/u013343114/article/details/112463703