继承
使用继承可以节省空间,减少代码长度
访问方式
- public:
- 本类中,同一个包下的其他类里,任意包下的子类里,任意包下的任意类里
- protected:
- 本类中,同一个包下的其他类里,任意包下的子类里
- 缺省:
- 本类中,同一个包下的其他类里
- private:
- 本类中
*任意包下的子类内能够访问potected类型的成员
但是子类对象无法访问potected类型的成员(仅限子类内部访问)
单继承
java的继承均为单继承,子类无法同时继承多个父类,但是支持多层继承
使用接口可以实现类似多继承的效果
Object类
Object类是所有类都默认直接或间接继承的父类
方法重写
当父类对象的方法不符合子类需求时,可以在子类重写与父类相同的方法,调用时采用就近原则,调用子类的新方法
- 注意事项:
- 1.方法重写前加@Override注解 可以检查重写格式正确性,提高代码可读性
- 2.子类重写父类方法时,访问权限需要>=父类方法权限(public>protected>缺省)
- 3.重写方法的返回值范围要<=父类返回值范围
- 4.不能重写私有方法,静态方法
子类中访问其他成员的特点:
就近原则(局部>本类>父类)
局部-直接访问/本类-this.X访问/父类-super.x/祖先类super.super…
子类中构造器的特点
- 先调用父类构造器再执行自身构造器(同C++)
- 如果父类没有无参构造器,子类构造器必须指定选择父类的有参构造器[super(a,b)]否则产生报错
- 可以用this(A,B)调用该类的构造器(在一个函数内不能同时出现this()和super())
- this()和super()调用都必须是构造函数的第一行语句
多态
定义:有继承或实现关系,存在父类引用子类对象,存在方法重写(只有对象和行为具有多态,成员变量没有多态)
People p1 = new Student();
此时People为引用类型 而Student为实际类型,函数根据实际类型来访问,变量通过引用类型访问
好处:
- 1.多态形势下,右边的对象时解耦合的,方便扩展和维护
- 2.定义方法时,使用父类类型的形参,可以接收一切子类对象,扩展性更强,更便利
- public static void f(people p)//可以接收所有以people为父类的子类对象
问题:
多态中不能使用子类的独有功能
解决:
强制类型转换 -> 存在继承或实现关系可以在编译阶段进行强制类型转换
如:Student s1 = (Student) p1;//People p1
问题:
编译时期有继承关系就可以强转,但是运行时容易出现异常
People p1 = new Student();
Teacher t1 = (Teacher)p1;
编译器认为p1实际对象为People但实际值为Student [异常ClassCastException]
解决:
使用关键字instanceof判断当前对象的真实类型
if(p1 instanceof Student)
Student s2 = (Student) p1;
else
Teacher s2 = (Teacher) p1;
抽象
使用abstract修饰的类或方法称为抽象类/方法
抽象类
- 抽象类中不一定要有抽象方法,有抽象方法的类一定是抽象类
- 抽象类中可以有普通类的所有成员(变量,方法,构造器)
- *抽象类不能创建对象,仅作为父类使用,让子类继承并实现
- 如果子类继承抽象类,必须重写完抽象类的所有抽象方法,否则这个子类也要定义为抽象类
抽象方法
用abstract修饰,只有方法签名,不能有方法体
使用场景:
父类知道每个子类的行为,但每个子类的方法实现不一样,父类可以定义为抽象方法,由子类重写实现,设计成抽象类可以更好的支持多态
//将f方法定义为抽象方法,然后让两个类继承一个抽象父类,并重写f方法,就可以实现共用一个方法的效果
public abstract class Parent {
public void f(xxx) {
//代码块A
implement();
//代码块B
}
public abstract void implement();
}
public class Child1 extends Parent {
@Override
public void implement() {
//实现1
}
}
public class Child2 extends Parent {
@Override
public void implement() {
//实现2
}
}
接口
使用关键字interface定义接口,(JDK8之前)
接口里只能有成员变量和成员方法(默认为常量,抽象方法)
接口不能创建对象,接口是用来被类实现(implements)的,实现接口的类被称为实现类
一个类可以实现多个接口
修饰符 class 实现类 implements 接口1,接口2,…{}
优点:
- 弥补了单继承的不足,一个类可以同时实现多个接口
- 让程序可以面向接口编程,程序员可以灵活方便的切换各种业务实现
- 增强接口能力,便于扩展和维护项目
JDK8开始新增的三种方法
默认方法
用 default 修饰的非抽象方法,它可以在接口中提供一个默认的实现,而不需要实现类去重写它
默认方法只能通过接口的实现类的对象来调用,不能通过接口名来调用
如果一个类实现了多个接口,而这些接口中有相同签名的默认方法,那么这个类必须重写这个默认方法,否则会有编译错误
私有方法
用 private 修饰的方法,它可以在接口中封装一些辅助性的逻辑,而不暴露给外部
私有方法只能在接口内部被调用,不能被接口的实现类或子接口继承或访问
私有方法可以是静态的或非静态的,但不能是默认的
私有方法可以在默认方法或其他私有方法中访问
静态方法
用 static 修饰的方法,它可以在接口中定义一些与实例无关的操作,而不需要实现类去重写它
静态方法只能通过接口名来调用,不能通过接口的实现类的对象或子接口来调用
静态方法也不能被接口的实现类或子接口继承或重写
接口的多继承
一个接口可以同时继承多个接口
注意事项
- 一个接口继承多个接口,如果多个接口中存在方法签名(方法名+参数类型)冲突,则不支持多继承(相同的方法签名返回值也要相同)
- 一个接口实现多个接口,如果多个接口中存在方法签名(方法名+参数类型)冲突,则不支持多实现
- 如果一个类同时继承了父类A和实现了接口B,对于A和B中同名的默认方法,实现类会优先调用父类的方法
- 如果一个类实现了多个接口,多个接口中存在同名默认方法,会产生冲突(解决方法:重写(Override)同名的默认方法)
final关键字
作用:修饰类,方法,变量
- 修饰类:最终类,不能被继承
- 修饰方法:最终方法,不能被重写
- 修饰变量:常量,只能被赋值一次
常量:使用static final修饰的成员变量叫做常量
作用:记录配置信息
优点:可读性,维护性好,性能与使用字面量相同
命名规范:使用大写英文单词,多个单词用下划线链接(SCHOOL_NAME)