1、继承的概念和特点
1、什么是继承:继承是一种类与类之间的关系,使用已存在的类定义作为基础建立新的类,叫做父类。新类的定义可以增加新的数据和新的功能,也可以用父类的功能,这就是继承。子类在继承父类的时候不能选择性的继承。
2、继承的关系:满足A is a B的关系就可以形成继承关系。
2、继承的实现
1、使用关键字 extends 来实现继承。java中的继承只能是单继承,一个子类只有它唯一一个父类,好比一个孩子只有一个亲爹。
2、子类只能继承父类的非私有成员,然后子类的私有成员不能被兄弟类访问到:父类是无法访问到子类的特有成员的。即使子类的特有成员是使用public来修饰的。
package com.imooc.animal;
public class Animal {
private String name; //昵称
private int month;//月份
private String species;// 品种
public Animal(){
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getMonth() {
return month;
}
public void setMonth(int month) {
this.month = month;
}
public String getSpecies() {
return species;
}
public void setSpecies(String species) {
this.species = species;
}
public void eat() {
System.out.println(this.getName()+"在吃东西");
}
}
3、下面我们创建一个猫的子类和狗的子类去继承动物的父类
package com.imooc.animal;
public class Cat extends Animal{
private double weight;//体重
public Cat() {
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
public void run() {
System.out.println(this.getName()+"是一只"+this.getSpecies()+"的猫");
}
}
package com.imooc.animal;
public class Dog extends Animal {
private String sex;//性别
public Dog() {
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public void sleep() {
System.out.println(this.getName()+"现在"+this.getMonth()+"大了,它在睡觉");
}
//子类方法的重写
public void eat() {
System.out.println(this.getName()+"今天不想吃东西");
}
}
3、访问修饰符的分类和作用:
1、首先要确定的就是访问修饰符的个数,其实有4个,除了public,private,protected,还有默认,就是没有修饰符的情况。
2、private:只允许在本类中进行访问
3、默认:允许在同类、同包子类,同包非子类中访问、跨包一律不允许访问。
4、protected:允许在同类、同包子类,同包非子类、跨包子类中访问,跨包非子类不能访问。
5、public:只要正常加载、允许在任意位置访问
4、方法的重写
4.1方法重写的概念和特点
1、子类想实现和从父类继承来的方法不一样的表现形式,就要使用方法的重写;
2、方法重写的语法规则,子类重写父类的方法时:
(1)方法的方法名、参数类型,顺序,个数。都要与父类继承的方法相同。
(2)但是方法的参数名称和返回值没有强制性的要求相同。
(3)但是方法的访问修饰符是可以允许有变化的。
3、虽然重写的概念在java中仅限于方法上面,但是在子类中也是可以去定义和父类重名的属性的。
4.2、访问修饰符对方法重写的影响
1、结论:重写方法的访问修饰符访问范围需要大于等于父类的方法访问范围。好比父母希望自己的孩子活的比自己好,走的更远。
5、super关键字
1、super是什么:super代表的就是父类的引用,通过super可以访问父类当中允许被子类派生的任意成员。
2、现在可以想一下,我们在前面那个动物的类中的构造函数:
public Animal(){
}
是这样的,使用public修饰的,是不是意味着父类的构造函数也能被重写和继承呢?
答案是:父类的构造函数不允许被继承,也不允许被重写。但是,父类的构造是整个继承学问中最重要的!
6、继承的初始化顺序
1、子类对象的初始化过程:先执行class.order将相关的类加载到虚拟机当中--->
2、--->进入父类--->加载父类的静态成员--->加载父类的静态代码块--->
3、--->进入子类--->加载子类的静态成员--->加载子类的静态代码块---->
4、--->进入父类--->加载父类的构造代码块--->加载父类的构造函数---->
5、--->进入子类--->加载子类的构造代码块--->加载子类的构造函数
6、特别注意:我们在java.lang中有个Object类,是所有类的父类,底层的子类要找到自己所有父辈级的类直到找到Object。
7、在访问静态成员和静态代码块的时候,访问修饰符不会影响加载顺序,跟代码的书写位置有关,即顺序执行静态内容:
static{
System.out.println("静态代码块")
}
private static int st=22;
public static int op=33;
写成上面这样,顺序就是static{},过来是st,最后是op,按照顺序执行。
private static int st=22;
public static int op=33;
static{
System.out.println("静态代码块")
}
写成上面这样,顺序就是st,过来是op,最后是static{},还是依次执行
所以结论还是:静态内容部分的访问顺序:访问修饰符不会影响加载顺序,跟代码的书写位置有关,即顺序执行静态内容。
8、在父类存在构造函数重载的时候,默认子类调用的是父类的无参构造方法。这个就是我们之前说的为什么父类的无参构造为什么这么重要,因为在没有父类的无参构造时,子类就默认找不到父类的无参构造,程序都不能编译过去。所以虽然父类的构造函数不继承也不能重写,但作用举足轻重啊!
9、当我们不想去调用父类的无参构造,我们就要使用super去调用父类的其他可以被访问的构造,显式调用父类的有参构造,使用super(参数1,参数2.....)方式的代码写在子类构造函数的第一行:比如父类的构造重载是这样:
public Animal(){
System.out.println("我是父类的构造函数");
}
public Animal(int month,String name) {
System.out.println("我是父类的构造函数的有参重载");
}
那么子类的构造应该是这样:
public Cat(int month,String name) {
super(month,name); //使用super显式去调用父类有参构造函数,写在子类构造函数的第一行
System.out.println("我是子类构造函数");
}
7、this&super
1、this是当前类对象的引用,super是父类对象的引用。
2、this和super都不能在静态方法中去调用。
3、this和super不能同时出现在子类的构造方法中,因为this和super都要抢占第一行的位置,所有一山不容二虎。