继承是多态的前提,没有继承就没有多态。
继承主要解决的问题:共性抽取。
父类,也可以叫基类,超类
子类,也可以叫派生类
继承关系中,子类可以拥有父类的内容,子类还可以拥有自己专有的内容。子类就是一个父类,子类可以被当作父类看待。子类is a父类。
格式:public classs 子类名称 extends 父类名称{}
在父子类的继承关系中,如果成员变量重名,则创建子类对象时,访问有两种方法:
直接通过子类对象访问成员变量:
等号左边是谁,就优先用谁,没有则向上找
间接通过成员方法访问变量:
该方法属于谁,就优先用谁,没有则向上找
当局部变量,子类成员变量和父类成员变量三者都同名
局部变量 直接写成员变量名
子类成员变量 this.成员变量名
父类成员变量 super.成员变量名
当子类成员方法和父类成员方法重名时,对象是谁,优先用谁,没有时向上寻找。
子类重写父类的成员方法:在继承关系中,方法的名称和参数列表都一样,则发生重写。
重写的特点:创建的是子类对象,则优先使用子类方法
注意:1、可以通过在方法前面添加注解@override,检测是不是正确的覆盖重写
2、子类方法的返回值必须小于等于父类方法的返回值
3、子类方法的权限必须大于等于父类方法的权限,public->protected->private
在继承关系中,父子类构造方法的访问特点:
1、子类构造方法当中默认隐含一个super();,所以一定是先调用父类的构造,后执行子类的构造
2、子类构造可以通过super关键字来调用父类构造的重载
3、super的父类构造调用必须是子类构造方法的第一个语句,一个子类只能调用一次父类的构造
总结:super关键字的三种用法:1、在子类的成员方法中,调用父类的成员变量
2、在子类的成员方法中,调用父类的成员方法
3、在子类的构造方法中,调用父类的构造方法
this关键字的三种用法:1、在本类的成员方法中,调用本类的成员变量
2、在本类的成员方法中,调用本类的成员方法
3、在本类的构造方法中,调用本类的另一个构造方法,如果有this,不能使用super,反之一样。
Java继承的三个特点:1、Java语言是单继承的,一个类直接的父类只能有一个。
2、Java语句可以多级继承
3、一个子类的父类是唯一的,但是一个父类可以拥有多个子类
抽象方法:如果父类当中的方法不确定如何进行方法体的实现,那么就应该是一个抽象方法
抽象方法的定义格式:在方法返回值前面加上abstract关键字,然后去掉大括号,直接分号结束。注意:抽象方法所在的类必须是抽象类才行,在class之前加上abstract即可。
如何使用抽象类和抽象方法的使用:1、不能直接使用new创建抽象类
2、必须用一个子类来继承抽象父类
3、子类必须覆盖重写抽象父类当中所有的抽象方法
4、创建子类对象进行使用
注意:1、抽象类中,可以有构造方法,是供子类创建对象时,初始化父类成员使用的
2、抽象类中,不一定包含抽象方法,但是抽象方法的类必须是抽象类
3、抽象类的子类,必须重写抽象父类中的所有的抽象方法,否则,编译无法通过,除非子类也是抽象类
接口(interface):一种公共的规范标准,是一种引用数据类型
定义一个接口: public interface 接口名称{接口内容;}
接口中可以包含的内容:1、常量
2、抽象方法
3、默认方法(Java8以上)
4、静态方法(Java8以上)
5、私有方法(Java9以上)
扩展:1、接口当中的抽象方法修饰符都是public abstract ,并且可以选择性省略。public abstract 返回值类型 方法名称(参数列表);
2、接口默认方法的定义 public default 返回值类型 方法名称(参数列表){方法体;},解决接口升级的问题。接口的默认方法可以通过接口的实现类的对象直接调用,也可以被实现类覆盖重写再调用。
3、接口的静态方法的定义:public static 返回值类型 方法名称(参数列表){方法体;},不能通过接口实现类的对象调用静态方法,应该通过接口名称直接调用静态方法。
4、接口的私有方法分为:1、普通私有方法 :private 返回值类型 方法名称 (参数列表){方法体;},解决多个默认方法之间重复代码的问题
2、静态私有方法:private static 返回值类型 方法名称 (参数列表){方法体;},解决多个静态方法之间重复代码的问题
5、接口的常量 : public static final 数据类型 常量名称 = 数据值
接口不能直接使用
1、必须有一个实现类来实现该接口
public class 实现类名称 implement 接口名称{}
2、接口的实现类必须覆盖重写接口中的所有抽象方法。
3、创建实现类的对象,进行使用
注意:1、如果实现类没有覆盖接口中所有的抽象方法,那么这个实现类自己必须是抽象类
2、接口没有静态代码块和构造方法
3、一个类的父类只有一个,但是一个类可以同时实现多个接口。
4、如果实现类所实现的多个接口中,存在重复的抽象方法,实现一次就好。
5、如果实现类所实现的多个接口中,存在重复的默认方法,实现类必须覆盖重写重复的默认方法。
6、一个实现类的父类方法和接口中的默认方法重复,优先使用父类方法。
接口的可以多继承的,多个父接口但在的抽象方法重复,没关系,默认方法重复,子接口要覆盖重写一个同名的默认方法
多态:一个对象拥有多种形态,子类形态和父类形态
多态的使用:父类引用指向子类 父类名称 对象名 = new 子类名称() 或者 接口名称 对象名 = new 实现类名称()
当使用多态时访问成员变量:1、直接通过对象名称访问成员变量,看等号左边是谁,优先用谁,没有则向上寻找
2、间接通过成员方法访问成员变量,看该方法属于谁,优先用谁,没有则向上寻找
在多态的代码中,成员方法访问的规则:看New的是谁,就优先使用谁,没有则向上寻找
使用多态的好处:无论右边new的时候换成哪个子类对象,等号左边调用方法都不会改变
对象的向上转型:其实就是多态的写法 父类名称 对象名 = new 子类名称();
注意:向上转型一定是安全的,从小范围到大范围,一旦向上转型为父类,那么就无法调用子类特有的内容
对象的向下转型:将父类对象还原成本来的子类对象, 子类名称 对象名 = (子类名称)父类对象
注意:必须保证对象本来创建的子类对象和向下转型的对象一致。
instanceof关键字:判断前面的对象能不能当作后面类型的实例 , 对象 instanceof 类名称 ,返回一个boolean值。用来判断是否能向下转换。
final关键字:最终的,不可变的
四种作用:1、用来修饰一个类,public final class 类名称{},表示当前的类不能有任何子类。
2、用来修饰一个方法,public final 返回值类型 方法名 (参数列表){方法体},表示当前的方法不能被子类覆盖重写。
3、用来修饰一个局部变量,final 数据类型 数据名称 = 表达式 ,一次赋值,不能更改,常量,注意基本数据类型值不变,引用类型地址不变
4、用来修饰一个成员变量,那么这个变量照样不变,但是因为成员变量具有默认值,所以用来final必须手动直接赋值或者构造方法赋值,且所有构造方法都进行了赋值。
四种权限修饰符:1、public
2、protected
3、default
4、private
对应的四种情况:1、同一个类:四种权限修饰符都能访问
2、同一个包:除了private 其他都可以
3、不同的包子类:除了private 和default 其他都可以
4、不同的包非子类:就public 可以
内部类:一个类的内部包含另一个类
分类:1、成员内部类
2、局部内部类(包含匿名内部类)
成员内部类:修饰符 class 类名称 {
修饰符 class 类名称{}
}
注意:内部类使用外部类,可以随意访问,外部类使用内部类必须使用内部类对象
使用内部类:1、在外部类的方法当中,使用内部类,然后在main只是调用外部类的方法
2、直接使用,外部类名称.内部类名称 对象名 = new 外部类名称().new 内部类名称()
内部类同名变量访问:如果出现重名的现象,使用外部类名称.this.变量名称 访问外部类成员变量。
局部内部类:只有当前所属的方法才能使用它,出了这个方法外面就不能用
修饰符 class 外部类名称{
修饰符 返回值类型 外部类方法名 (参数列表){
class 局部内部类名称{
}
}
}
注意:局部内部类如果希望访问所在方法的局部变量,那么这个局部变量必须是有效final。(final可写可不写,但是局部变量必须不能改变)
类的权限修饰符:
外部类: public /default
成员内部类:public /protected/ private/default
局部内部类:什么都不写
匿名内部类:如果接口的实现类或者父类的子类,只需要使用一次,这种情况下就可以省略掉该类的定义,而改为使用匿名内部类
定义格式: 接口名称 对象名 = new 接口名称 (){需要覆盖的方法;}