1、继承
1.1概念
继承就是子类继承父类的属性和行为,使得子类对象拥有父类相同的属性、相同的方法。子类可以直接访问父类的非私有的属性和行为。
1.2特点
- 子类可以拥有父类的“内容”。
- 子类还可以拥有自己专有的内容。
在继承的关系中,“子类就是一个父类”。也就是说,子类可以被当做父类看待。
例如父类是员工,子类是讲师,那么“讲师就是一个员工”。关系:is-a。
1.3格式
public class 子类名称 extends 父类名称 {
// ...
}
1.4继承成员变量访问的特点
1.4.1成员变量不重名
如果子类和父类中的成员变量不重名,这时访问变量是没有任何影响的;
代码示例:
public class Fu {
//父类成员变量
int numFu = 10;
}
public class Zi extends Fu{
//子类成员变量(不重名)
int numZi = 20;
}
public class demo01Extends {
public static void main(String[] args) {
Fu fu = new Fu();//创建父类对象
System.out.println(fu.numFu);//10
Zi zi = new Zi(); //创建子类对象
System.out.println(zi.numFu);//10
System.out.println(zi.numZi);//20
}
}
1.4.2成员变量重名
在父子类创建的继承关系中,如果成员变量重名,则创建子类对象时,访问方式有两种:
1、直接通过子类对象访问成员变量(等号左边是谁,就优先用谁,没有则向上找)
public class Fu {
//父类成员变量
int num = 10;
}
public class Zi extends Fu{
//子类成员变量(重名)
int num = 20;
}
public class demo01Extends {
public static void main(String[] args) {
Fu fu = new Fu();//创建父类对象
System.out.println(fu.num);//优先父类:10
Zi zi = new Zi(); //创建子类对象
//等号左边是谁,就优先用谁
System.out.println(zi.num);//优先子类:20
}
}
2、直接通过成员方法访问成员变量(方法属于谁,就优先用谁,没有则向上找)
public class Fu {
//父类成员变量
int num = 10;
//父类成员方法
public void methodFu(){
//使用本类当中的num
System.out.println(num);
}
}
public class Zi extends Fu{
//子类成员变量
int num = 20;
public void methodZi(){
//因为本类中有num,则使用本类的num
System.out.println(num);
}
}
public class demo01Extends {
public static void main(String[] args) {
Fu fu = new Fu();//创建父类对象
Zi zi = new Zi(); //创建子类对象
//methodFu方法在父类,则优先使用父类
zi.methodFu();//10
zi.methodZi();//20
}
}
1.5区分子类方法重名的三种变量
局部变量,直接写
本类的成员变量,this.成员变量名称
父类的成员变量,super.成员变量名称
代码示例:
public class Fu {
//父类成员变量
int num = 10;
}
public class Zi extends Fu{
//子类成员变量
int num = 20;
public void method(){
//局部变量
int num = 30;
System.out.println(num);//使用局部变量:30
System.out.println(this.num);//使用本类的成员变量:20
System.out.println(super.num);//使用父类的成员变量:10
}
}
public class Demo01Extends {
public static void main(String[] args) {
//创建子类对象
Zi zi = new Zi();
//调用子类方法
zi.method();
}
}
1.6继承中成员方法的访问特点
1.6.1成员方法不重名
如果子类和父类中的成员方法不重名,这时访问变量是没有任何影响的;
代码示例:
public class Fu {
//父类成员方法
public void methodFu(){
System.out.println("父类方法执行");
}
}
public class Zi extends Fu{
//子类成员方法
public void methodZi(){
System.out.println("子类方法执行");
}
}
public class Demo01ExtendsMethod {
public static void main(String[] args) {
//创建子类对象
Zi zi = new Zi();
zi.methodFu();//父类方法执行
zi.methodZi();//子类方法执行
}
}
1.6.2成员方法重名
在父子类的继承关系当中,创建子类对象,访问成员方法的规则:
创建对象是谁,就优先用谁,没有则向上找。
代码示例:
public class Fu {
//父类成员方法
public void method(){
System.out.println("父类方法执行");
}
}
public class Zi extends Fu{
//子类成员方法
public void method(){
System.out.println("子类方法执行");
}
}
public class Demo01ExtendsMethod {
public static void main(String[] args) {
//创建子类对象
Zi zi = new Zi();
zi.method();//创建对象为子类,则使用子类方法:子类方法执行
}
}
1.7重写(覆盖重写)-----子类父类中出现重名的成员方法
概念:在继承关系当中,方法的名称一样,参数列表也一样。
重写(Override):方法的名称一样,参数列表也一样。
重载(Overload):方法的名称一样,参数列表不一样。
方法的覆盖重写的特点:
- 必须保证父类之间的方法名称,参数列表都相同。
- @Override写在子类方法前面,用来检测是不是有效的正确覆盖重写,可写可不写。
- 子类方法的返回值【必须小于等于】父类方法的返回值范围;Object类是所有类的最高父类。
- 子类方法的权限【必须大于等于】父类方法的权限修饰符(public > protected > (default:不是关键字,是什么都不写) > private)。
1.8继承中构造方法的访问特点
1、子类构造方法当中有一个默认隐含的“super()”调用,所以一定是先调用的父类构造方法,在调用子类构造方法。
代码:
public class Fu {
//父类构造方法
public Fu(){
System.out.println("父类构造方法");
}
}
public class Zi extends Fu{
//子类构造方法
public Zi(){
System.out.println("子类构造方法");
}
}
public class Demo01Constructor {
public static void main(String[] args) {
//创建子类对象
Zi zi = new Zi();
}
}
结果:
2、子类构造可以通过super关键字来调用父类重载构造。
代码:
public class Fu {
public Fu(int num){
System.out.println("父类有参构造方法");
}
}
public class Zi extends Fu{
public Zi(){
super(2);//调用父类重载的构造方法
System.out.println("子类构造方法");
}
}
public class Demo01Constructor {
public static void main(String[] args) {
Zi zi = new Zi();
}
}
结果:
3.super的父类构造调用,必须是子类构造方法的第一个语句,不能一个子类构造方法调用多个super构造。-----子类构造方法能用
如果super关键字不在第一个语句,代码就会报错。
例如:
public class Zi extends Fu{
public Zi(){
System.out.println("子类构造方法");
super(2);//会报错
}
}
总结:
子类必须调用父类构造方法,不写则赠送super(),写了则用指定的super()调用。
1.9super关键字(在子类中使用,访问父类内容)的三种用法
- 在子类的成员方法中,访问父类的成员变量。
- 在子类的成员方法中,访问父类的成员方法。
- 在子类的构造方法中,访问父类的构造方法。
代码:
public class Fu {
int num = 10;
public Fu(){
System.out.println("父类构造方法");
}
public void method(){
System.out.println("父类成员方法");
}
}
public class Zi extends Fu{
int num = 20;
public Zi(){
super();//父类构造方法
System.out.println("子类构造方法");
}
public void method(){
System.out.println(super.num);//访问父类的成员成员变量:10
super.method();//访问父类的成员方法:父类成员方法
System.out.println("子类成员方法");
}
}
public class Demo01Super {
public static void main(String[] args) {
Zi zi = new Zi();
zi.method();
}
}
2.0 this关键字(访问被类内容)的三种用法
- 在本类的成员方法中,访问本类的成员方法。
- 在本类的成员方法中,访问本类的另一个成员方法。
- 在本类的构造方法(无参)中,访问本类的另一个构造方法(有参),this在第一句。
代码:
public class Zi extends Fu{
int num = 20;
public Zi(){
//在本类的构造方法中,访问本类的另一个构造方法。
this(4);//本类的无参构造,调用本类的有参构造
System.out.println("子类构造方法");
}
public Zi(int num){
}
public void method(){
//在本类的成员方法中,访问本类的另一个成员方法。
this.method1();//另一个成员方法
int num = 30;
System.out.println(num);//30
//在本类的成员方法中,访问本类的成员方法。
System.out.println(this.num);//20
}
public void method1(){
System.out.println("另一个成员方法");
}
}
2.1继承的三个特点
1、Java语言是单继承(一个类的直接父类只能有唯一一个)。
class A{}
class B extends A{}//正确
class C{}
class D extends A,C{}//错误
2、Java语言可以多层继承。
class A{}
class B extends A{}//正确
class C extends B{}//正确
顶层父类是Object类。所有的类默认继承Object,作为父类。
3、一个子类的直接父类是唯一的,但是一个父类可以拥有很多个子类。
class A{}
class B extends A{}//正确
class C extends A{}//正确
2、抽象类
2.1、抽象的概念
如果父类当中的方法不确定如何进行{}方法体实现,那么这就是一个抽象方法。
抽象方法:没有方法体的方法。
抽象类:包含抽象方法的类。
2.2、抽象方法
概念:使用 abstract 关键字修饰方法,该方法就成了抽象方法,抽象方法只包含一个方法名,而没有方法体。
格式:修饰符 abstract 返回值类型 方法名 (参数列表);
举例:public abstract void eat();
2.3、抽象类
概念:如果一个类包含抽象方法,那么该类必须是抽象类。
格式:abstract class 类名字 {
}
举例:public abstract class Animal {
public abstract void run();
}
2.4、抽象的使用
代码:
public abstract class Animal{
//创建抽象方法
public abstract void eat();
}
public class Cat extends Animal{
//覆盖重写父类中所有的抽象方法
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
public class Demo01Abstract {
public static void main(String[] args) {
//创建子类对象
Cat cat = new Cat();
//调用eat方法
cat.eat();
//不能直接创建new抽象对象
// Animal animal = new Animal();
}
}
2.5、注意事项
- 不能直接创建new抽象对象。
- 必须用一个子类继承父类。
- 子类必须覆盖重写抽象父类当中的所有抽象方法。
- 创建子类使用。
- 抽象类中,可以有构造方法,是供子类创建对象时,初始化父类成员使用的。