为热爱编程的你点赞!
学习SpringBoot实战课程 https://edu.csdn.net/course/detail/31433
学习SpringCloud入门课程 https://edu.csdn.net/course/detail/31451
面向对象系列:
类和对象
封装
继承
多态
static关键字和单例模式
接口和内部类
前言
本文我们开始探讨面向对象的另一个重要特征——继承,大家会学习到继承的相关概念、super关键字、继承中的构造方法、final关键字以及抽象方法等。
继承概述
现实中的继承:
程序中的继承:
可以由子类继承父类的成员(属性和方法),起到代码重用的作用
特点:
- 程序中的类分为父类和子类
- 子类可以继承父类,也可以说父类派生子类
- 子类可以继承父类的属性和方法,是一种代码重用的机制
如何判定两个类具有继承关系呢?
子类和父类具有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代表父类对象
作用有:
- 调用父类的属性
super.属性
- 调用父类的方法
super.方法(..)
- 调用父类的构造方法
super(参数);
super和this的区别:
- this代表当前类的对象,super代表父类的对象
- this可以调用当前类的属性和方法(包括自身特有和父类的)
super只能调用父类的属性和方法 - 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);
注意:
- 子类如果不写super,系统会默认调用父类无参的构造方法
- 调用父类有参构造方法时,子类必须使用super显式的调用父类的构造方法
- super()必须出现在子类构造方法的第一行
- 构造方法的调用,总是先调用父类的,再调用子类的
方法重写
什么是方法重写?
子类中的方法可以覆盖父类中的方法
方法重写的特点:
- 方法在子类和父类中
- 方法名相同
- 参数、返回值都相同
- 子类方法的访问修饰符不能比父类更严格
学生类重写父类的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关键字
用于修饰类、变量、方法
- 被final修饰的类,不能被继承
final class A{}
class B exends A{} //错误
- 被final修饰的变量变成常量,不能修改值
final int num = 2000;
num++; //错误
- 被final修饰的方法,不能重写
class A{
public final void test(){}
}
class B extends A{
public void test(){} //错误
}
抽象方法和抽象类
在实际开发过程中,有时候我们需要把某些方法的具体实现,推迟到子类中实现。
抽象方法的意义在于:
- 可以规范方法的定义(返回值类型、方法名、参数)
- 具体实现由子类完成
抽象方法:
public abstract 返回值 方法名(类型 参数);
抽象类
abstract class 类名{
}
修改Person类
/**
* 抽象类
*/
public abstract class Person {
....省略其他代码
//抽象方法
public abstract void eat();
}
注意:
- 一旦类中定义了一个抽象方法,这个类必须定义成抽象类
- 有抽象方法的类,必须是抽象类;抽象类不一定有抽象方法
抽象类的特点
- 抽象类不能实例化
- 抽象类必须由子类继承并实现其中的抽象方法,除非子类也是抽象的
结束
最后给大家留两个编程题:
1、定义交通工具类,属性:颜色、速度、耗油量;方法:移动、停止。
定义汽车类和轮船类继承交通工具,汽车类有品牌属性,有刹车方法
轮船有排水量属性,有抛锚方法。
创建汽车和轮船对象,并调用所有的方法。
2、定义一个家电类,定义功率、价格、品牌属性,定义启动方法用于输出这些属性。
定义一个电视类,继承家电类,添加播放方法。
创建电视对象,调用播放方法。
最后给家电添加有参的构造方法,在电视中用super调用父类构造方法。
大家如果需要学习其他Java知识点,戳这里 超详细的Java知识点汇总