一 继承
1.继承的由来
多个类中有相同成员变量和成员方法,那么我们会把这些共性抽取到另外一个类中,
这时多个类只需要继承刚刚抽取出来这个类即可
2.父类 和 子类
一个类A 继承了 类B,那么 类B称为父类/超类/基类(superclass)
类A称为子类/派生类(subclass)
3.继承的格式:
public class Fu{
//成员变量
//成员方法
}
public class Zi extends Fu{
子类自动拥有父类的所有成员变量和成员方法
(私有的不能直接使用)
}
好处:a.提高代码的复用性 b.为多态提供了前提
4.继承后子父类成员方法的特点
如果子父类的成员方法不同名,那么子类调用成员方法时,没有任何歧义
如果子父类的成员方法同名,那么子类调用成员方法时,优先调用子类自己的成员方法
如果把子类那个成员方法注释掉,才会调用父类继承的
如果把父类那个成员方法也注释掉,那么程序会报错
总结: 无论是成员变量 还是 成员方法,子类有优先访问子类自己的,子类没有才会访问父类的(就近原则),父类没有才会报错!!!!
5.方法的重写
方法的重载(overload): 在同一个类中,有方法名一样,但是参数列表不一样的多个方法
方法的重写(override): 在子父类中,出现除了方法体其他都一样的方法,此时子类中这个方法称为方法的重写
什么时候需要方法的重写:
当子类继承父类的方法后,发现父类的方法功能不足,那么子类就可以重写该方法
在重写该方法时,如果某一部分功能父类已经实现了,只需要通过super.方法名 调用父类已经实现功能即可
其他未实现的功能,子类在自己添加上去
6.关键字 this 和 super
this的作用: 区分局部变量和成员变量的同名问题
super的作用: 区分本类成员变量和父类成员变量同名问题
格式:
this.成员变量 访问本类的成员变量
super.成员变量 访问父类的成员变量
this.方法名() 调用本类自己的成员方法
super.方法名() 调用父类的成员方法
7.继承后构造方法的特点
构造方法的特点: 不写任何返回值类型,方法名必须和类名一样
构造方法子类是不能继承,跟没有继承的说法
特点: 子类的任何构造方法,第一行默认会使用super()调用父类的无参构造
思考:能不能不调用父类的无参构造,而是调用父类的有参构造???
能!!!但是必须程序员手动调用super(参数);
8.构造方法总结
super() 调用父类的无参构造
super(参数) 调用父类的有参构造
this();调用子类自己的无参构造
this(参数);调用子类自己的有参构造
无论是this()还是super()都必须写在第一行,而且不能同时出现
9.继承之后 子类对象的内存图
父类空间优先于子类对象产生
在每次创建子类对象时,先初始化父类空间,再创建其子类对象本身。目的在于子类对象中包含了其对应的父类空间,
便可以包含其父类的成员,如果父类成员非private修饰,则子类可以随意使用父类成员
11. 继承的特点
a.java中类和类之间叫单继承 (一个子类 只能有一个亲爹)
b.java中类和类之间可以多层继承(一个子类 只能有一个父类 该父类也可以有自己的父类)
二.多态
1.多态的概念
一个对象的多种形态:
H2O
固态: 冰,雪花
液态:溪水,海水
气态:蒸汽
一个学生
在家: 儿子,父母
在社会: 员工,老板,包工头
在学校: 学生,学霸,学渣,学神
2.多态的前提
a.继承 或者 实现
b.必须有方法的重写(Override)
3.多态的体现
语言表达:父类类型的变量 指向了 子类类型的对象
代码表达:Fu ff = new Zi();
多态的赋值:直接赋值:
父类类型 变量名 = new 子类类型();
爷爷类型 变量名 = new 孙子类型();
爷爷类型 变量名 = new 父类类型();
多态的赋值:间接赋值:
子类类型 变量名 = new 子类对象();
父类类型 对象名 = 变量名;
多态的赋值:参数赋值:
子类类型 对象名 = new 子类类型();
method(对象名);
public static void method(父类类型 变量名){
父类类型 变量名 = new 子类类型();
}
4.多态调用方法时的特点**************
编译阶段 看父类
运行阶段 看子类
多态只能调用子父类共有的方法,不能调用子类特有的方法
5.多态的好处***********
提高程序扩展性(灵活性)
6.多态的弊端
多态只能调用子父类共有的方法,不能调用子类特有的方法
7.多态弊端的解决方案–转型
数据类型转换---基本类型
自动转换 --- double d = 10;
强制转换 --- int a = (int)3.14;
转型---引用类型
向上转型: Animal an = new Cat(); //也就是多态
向下转换: Cat cc = (Cat)an;
8.转型的异常
Animal a = new Cat(); //多态,向上转型
a.eat(); // 调用的是 Cat 的 eat
Dog d = (Dog)a; //运行报错:ClassCastException (类型转换异常)
//因为a之前存储的是cat类型不是Dog类型
d.watchHouse();
9.转型异常的解决方案
运算符 instanceof
格式:
对象 instanceof 类型
结果:
如果对象是属于右边的类型 那么返回true
如果对象不属于右边的类型 那么返回false
public class Test {
public static void main(String[] args) {
// 向上转型
Animal a = new Cat();
a.eat(); // 调用的是 Cat 的 eat
// 判断a是否是Cat类型
if (a instanceof Cat){
Cat c = (Cat)a; //向下转型
c.catchMouse(); // 调用的是 Cat 的 catchMouse
} else if (a instanceof Dog){//判断a是否是Dog类型
Dog d = (Dog)a; //向下转型
三 static关键字
1.static关键字的用法和作用
用法:static可以修饰类的成员
格式:
public class 类名{
static int age;
public static void eat(){
}
}
static的作用:
被static修饰的成员,称为类成员,属于类,不属于某个对象
2.static修饰成员变量—类变量.静态变量
特点: 被static修饰的成员变量,不属于对象,属于类,在内存中只有一份,被所有对象共享
内存图:
https://blog.csdn.net/sapodilla/article/details/49494165
我的图,上传失败…
推荐访问静态变量的方式:
对象名.静态成员变量(不推荐)
类名.静态成员变量(推荐)
3.static修饰成员方法—类方法,静态方法
被static修饰的方法,可以直接使用类名调用,不需要使用对象调用(工具类)
推荐调用静态方法的方式
对象名.静态方法名();//不推荐
类名.静态方法名();//推荐
4.扩展:
静态和非静态的相互访问
结论:
静态与静态,非静态与非静态之间可以相互访问
但是 静态不能访问非静态 非静态却可以访问静态
为什么:因为他们的生命周期不一样
静态: 随着类加载而存在,出现的时间早(秦始皇)
非静态:随着对象的创建而存在,出现的时间晚(我们)
5.static还可以修饰代码块—静态代码块
a.定义位置
直接定义在类的内部
格式:
public class 类名{
static{
这里就是静态代码块中的代码
}
}
b.特点
静态代码块,随着类的加载而执行,而且只会执行一次
所以执行优先级,高于构造,高于main方法
c.作用
用来初始化一些数据(坦克大战,数据库驱动)
6.回顾
1)static可以修饰哪些成员?
a.成员变量:
该成员变量 变成类变量,类变量在内存只有一个,被所有对象共享
b.成员方法
该成员变量 变量类方法,可以通过类名直接调用方法(制作工具类)
c.静态代码块
随着类的加载立刻执行(初始化一些数据,一些静态变量)
2).使用static修饰的成员可以怎样被访问?
对象名.静态变量名
对象名.静态方法名()
=============以上可以通过对象访问,但是不推荐================
类名.静态变量名
类名.静态方法名();
3).以下哪些可以使用static修饰:
A).类 B).成员属性 C).成员方法 D).局部变量 E).构造方法
ABC
4)static代码块什么时候会被执行?
随着类加载 立刻执行
5).如果一个类中同时定义了"静态代码块"和"构造方法",当第一次创建这个类的对象时,它们会被怎样执行?
先静态代码块 再执行构造方法
第二次再创建对象时,它们会被怎样执行?
只执行构造方法,不执行静态代码块
四.练习
1. 使用继承的方式,在子类特有的show方法中打印父类int类型成员变量的值;
2.使用继承的方式完成某人自我介绍的功能;
具体要求:
1:父类中使用私有的成员变量表示姓名和年龄;
2:父类中用show方法表示自我介绍的行为,具体内容是:
我叫:xxx,今年xx岁;
3:在子类的show方法中调用父类的show方法;
3.使用代码模拟学生和老师信息管理系统;
具体要求:
1:老师和学生都是人,都包含姓名和年龄属性(要求私有),都包含自我介绍方法show,在show方法中展示个人信息.例如:
我是xxx,今年xx岁.
2:老师有讲课方法teach,方法的内容是: 我是一名老师,我在讲课;
3:学生有学习方法study,方法的内容是: 我是一名学生,我在学习;
4:编写测试类,要求创建老师和学生对象的时候,使用多态方式,且调用每个对象的show方法.
5:若是老师调用teach方法;若是学生调用study方法.
打印效果:
我是张老师,今年35岁
我是一名老师,我在讲课
我是小明,今天20岁
我是一名学生,我在学习
4.使用代码模拟学生和老师信息管理系统;
具体要求如下:
1:老师和学生都是人,都包含姓名和年龄属性(要求私有)
2:老师包含特有的属性:所讲课程course;特有讲课方法teach,方法的内容是: 我是xxx,今年xx岁,正在讲xxx课程;
3:学生包含特有的属性:考试分数score;特有考试方法exam,方法的内容是: 我是xxx,今年xx岁,考了xx分;
4:编写老师和学生的测试类,分别测试老师和学生的讲课和考试方法;要求创建老师和学生对象的时候,使用带参数的构造方法创建对象;
打印效果:
我是王老师,今天38岁,正在讲java课程
我是小丽,今天18岁,考了99分