继承:
小类归于大类,子类归于父类。
类是对对象的抽象,继承是对某一批类的抽象,从而实现对现实世界更好的建模。
提高代码的复用性!
extends意思是“扩展”。子类是父类的扩展
不同的叫法:超类、父类、基类 子类、派生类
子类与父类是is-a的关系
为什么使用继承?
使用继承优化后:方便修改代码,减少代码量
如何使用继承?
- 编写父类
- 编写子类,继承父类
例:class Pet{//公共的属性与方法}
class Dog extends Pet {//子类特有的属性与方法}
继承关键字:extends,只继承一个父类
Java是单继承关系,一个父类可以有多个子类,但是一个子类只能有一个父类。类似于现实世界中的血缘父子关系。
super关键字:
super是直接父类的引用。
可以通过super来访问父类中被子类覆盖的方法或属性。
普通方法:
没有顺序限制,可以随便调用。
构造函数中:
任何类的构造中,若是构造函数的第一行代码没有显式调用super(…);那么
Java默认都会调用super();作为父类的初始化函数。所以你这里的super();加不加都无所谓。(优先调用父类的构造方法)
理解继承:
使用super关键字,super代表父类的对象
子类访问父类成员
-访问父类的构造方法(在子类构造方法中调用且必须是第一句)
super();
super(name);
-访问父类的属性
super.name;
-访问父类的方法
super.print();
子类可以继承父类的所有资源吗?
不能被继承的父类成员:
- 不能直接访问private成员
- 子类与父类不在同包,使用默认访问权限的成员
- 构造方法
访问修饰符protected可以修饰属性和方法,本类、同类、子类可以访问
多重继承关系的初始化顺序:父类优先与子类
父类属性→父类构造方法→子类属性→子类构造方法
何时使用继承?事物之间符合is-a的关系设计使用继承。继承与真是世界类似:藏獒是一种狗。
继承是代码重用的一种方式。将子类共有的属性和行为放到父类中。
继承小结:
-通过继承可以简化类的定义,实现代码的重用
-子类继承父类的成员变量和成员方法,但不继承父类的构造方法
-Java中只有单继承,没有像C++那样的多继承。多继承会引起混乱,使得继承链过于复杂,系统难于维护。就像我们现实中,如果你有多个父母亲,那是一个多磨混乱的世界啊。多继承,就是为了实现代码的复用性,却引入了复杂性,使得系统之间的关系混乱。
-java中的多继承,可以通过接口来实现
-如果定义一个类时,没有调用extends,则它的父类是:java.lang.Object。(顶级父类)
方法的重写(Override)
在子类中可以根据需要对基类中继承来的方法进行重写。
重写方法必须和被重写方法具有相同方法的名称、参数列表和返回类型。
重写方法不能使用比被重写方法更为严格的访问权限。(由于多态)
构造方法不能被继承,因此不能被重写。
方法重载小结:
方法重载的规则
-方法名相同
-参数列表相同
-返回值类型相同或者是其子类
-访问权限不能严于子类
方法重载与重写
位置 | 方法名 | 参数表 | 返回值 | 访问修饰符 | |
方法重写 | 子类 | 相同 | 相同 | 相同或是其子类 | 不能比父类更严格 |
方法重载 | 同类 | 相同 | 不相同 | 无关 | 无关 |
super继承关键字来访问父类的成员(小结)
-super只能出现在子类的方法和构造方法中
-super调用构造方法时,只能是第一句
-super和this不能同时出现在构造方法中
-super不能访问父类的private成员
-super和this都不能在static方法中
抽象类与抽象方法
抽象类是把相同但不确定的事物提取(抽象)出来,为了以后的具象化重用。(音:chong)
定义成抽象类的目的就是为了在非抽象类的子类中实现抽象类
Java中使用抽象类,限制实例化。因为有的事物的实例化没有意义。
public abstract class Pet{…}
抽象方法:由于有些方法在每个子类的实现不同。
public abstract void print(); //没有具体方法体。
abstract也可用于方法——抽象方法
-抽象方法没有方法体。
-抽象方法必须在抽象类中,抽象类中可以没有抽象方法。
-抽象方法必须在子类中实现,除非子类是抽象类。
final用法
某个类不希望再被其他类继承,使用final类。
方法不希望被重写,使用final方法。
属性值不希望被修改,使用常量。
使用final修饰引用型变量,变量不可以再指向另外的对象。
使用final修饰引用型变量,变量的值是固定不变的,而变量所指向对象的属性值是可变的。
final关键字用法
含义:这是无法改变的 或者 终态的
可以修饰非抽象类、非抽象类成员方法和变量。
可能出于两种理解而需要阻止改变:
设计和效率
- final类
final类不能被继承,因此final类的成员方法没有机会被覆盖,默认都是final的。在设计类的时候,如果这个类不需要子类,类的实现细节不允许改变,并且确信这个类不能被扩展,那么就设计为final类。final方法不能被子类的方法覆盖,但可以被继承。
- final方法
如果一个类不允许其子类覆盖某个方法,则可以把这个方法声明为final方法。
使用final方法的原因有二:
- 把方法锁定,防止任何继承类修改它的意义和实现。
- 高效。编译器在遇到调用final方法时候会转入内嵌机制,大大提高执行效率。
- final变量(常量)
用final修饰的成员变量表示常量,只能被赋值一次,赋值后值无法改变!
final修饰的变量有三种:静态变量、实例变量和局部变量,分别表示三种类型的常量。
另外,final变量定义的时候,可以先声明,而不给初值,这种变量也称为final空白,无论什么情况,编译器都确保空白final在使用之前必须被初始化。但是,final空白在final关键字final的使用上提供了更大的灵活性,为此,一个类中的final数据成员就可以实现依对象不同而有所不同,却又保持其恒定不变的特征。
- final参数
当函数参数为final类型时,你可以读取使用该参数,但是无法改变该参数的值。
例:public void fin(final num){} //num是final类型的,值不允许改变
注:父类的private成员方法是不能被子类方法覆盖的,因此private类型的方法默认是final类型的。
final不能用于修饰构造方法。
Object类
- Object类是所有类的父类
一个类如果将没有使用extends显示的继承另外一个类,那么这个类就继承自Object类。
- 源码解析(涉及到Object中常用的10个方法)
getClass()、hashCode()、equals(Object)、clone()、toString()、notify()、notifyAll()、wait()、wait(long,int)
finalize()方法为过时的方法或者说是不推荐的方法,主要作用是标识在堆中的对象哪些是没有被引用的,方便JVM中的GC进行垃圾回收。
3、对象的比较“==”与equals()
a.==:
(1)比较两基本类型变量的值是否相等
(2)比较两个引用类型的值即地址是否相等,即是否指向同一个对象。
b.equals():
(1)比较地址(对象)是否相同
(2)比较两对象的内容是否相同
c:自定义类须重写equals(),否则其对象比较结果总是false。
通过阅读API帮助文档Object源码可知,equals()方法的实现是用“==”完成的
即,在Object中,==与equals()没有区别,
但是,在String类中,String类对Object中的equals()方法和HashCode()算法 进行了重写。
-equals()方法将此字符串与指定的对象比较。当且仅当该参数不为null,并且是
与此对象表示相同字符序列的String对象时,结果才为true。(比较的是对象的 值)
Java是一种单继承语言,也就是说,Java中所有的类都有一个共同的祖先,就是Object类,即使没有显示声明,编译器也会默认加上。该类有12个成员方法,分别是clone():Object、equals(Object):boolen、finallize():void、getClass()、hashCode():int、notify():void、notifyAll():void、toString():String、wait():void、wait(long):void、wait(long,int):void
getClass():返回某个对象在运行时的类型(被实例化的类),匿名内部类返回形式为系统自动生成的代码
clone():另存一个当前存在的对象
equals():判断两对象是否相等
hashCode():对象签名。该方法用来返回其所在对象的物理地址(哈希码值),常会和equals()方法同时重写,确保相等的两个对象拥有相等的.hashcode。
toString():1.一般来说通过重写该方法,返回一个String对象,用来标识自己(输出需要的那部分)。2.该方法在打印对象时被调用,将信息变为字符串返回,默认输出对象地址。
关于多线程机制:wait():void、wait(long):void、wait(long,int):void、notify():void、 notifyAll():void
关于垃圾回收:finalize()
继承深化
父类方法的重写:
“==”:方法名、形参列表相同。
“≤≤”:返回值类型和异常类型,子类小于父类。
“≥”:访问权限,子类大于等于父类。
构造方法调用顺序:
-根据super的说明,构造方法第一句总是:super(…)来调用父类对应的构造方法。
-先向上追溯到Object,然后依次向下执行类的初始化块和构造方法,直到当前子类为止.
关于代码实现:
- 发现类
- 发现类的属性
- 发现类的方法
- 优化设计:可以抽取父类或者检查abstract,final之类的
5、编写程序入口(编写测试代码运行)
梳理运行过程:1、实例化类的对象
2、调用方法实现业务等