java继承细节,继承内存布局和访问权限规则

访问权限

 

 

 

java继承细节

1.子类会继承父类所有的属性和方法,private的属性和方法不能直接访问,子类要通过父类提供的方法来访问到private属性和方法。

 

2.子类在创建对象,调用构造器时,肯定会连带父类的构造器也一起进行,即父类也要初始化,顺序是先进行父类构造器,后进行子构造器,不管是使用子类的哪一个构造器,都会先执行父类的默认无参构造器,如果没有默认无参构造器,那么必须使用super(形参列表)去指明是使用父类的哪一个构造器来完成父类的初始化,否则编译会报错。个人理解为,之所以这样做,是因为子类不能访问到private以及某些默认的属性,不能保证完成初始化,而用父类就肯定能完成初始化。

 

3.由于子类父类是相对而言的,所以一个子类在创建对象后要初始化时,进行的父类初始化不只是直接父类要进行,父类的父类,父类的父类的父类,一直往上到顶级父类object(java所有类都继承于它),这条线路上所有的父类都要进行初始化,并且是从顶级父类开始初始化,然后一直往下,直到当前正在初始化对象的子类。

 

4.super必须放在构造器第一行,this也是,所以同一个构造器这俩不能共存。

 

5.java只支持单继承,要实现继承多个类,只能是一层一层继承,比如A想继承B,C,那么可以让B继承C,然后A继承B,或者C继承B,然后A继承C

 

6.继承不能滥用,继承的初衷,是为了提高代码复用性,拓展性和可维护性,这个复用性是指:当遇到一些有共同部分的类时,不用在每个类都重复写这些共同部分的代码

比如篮球运动员和田径运动员

class BaskballPlayer {
    String name;
    int age;
    int finalChampion;
    int allStar;
}

class Athlete{
    String name;
    int age;
    int olympicChampion;
}

虽然他们有所区别,但也有很多同样的地方,比如名字年龄,那么如果在开发时还要写到其他种类的运动员,那么将会写很多的名字和年龄,这很花时间还没有什么意义,而且以后要是不需要显示运动员的年龄,那岂不是还要一个个去删?

而且修改或者删除时万一出错了,那更是崩溃中的崩溃,所以我们直接抽象出名字和年龄这两个属性,设一个运动员类,这样,每种运动员直接继承就行了,能少写很多代码,要是需要增删改查这两个属性也只需要直接在运动员类中操作即可,大大提高了维护性和拓展性。

class Player {
    String name;
    int age;
}

class BasketballPlayer extends  Player{
    int finalChampion;
    int allStar;
}

class Athlete extends  Player{
    int olympicChampion;
}

所以,继承是要子类和父类有相关性才继承,遵循“is-a”原则

比如person和music

person is a music?

no

music extends person  / /不合理

 

animal

cat is a animal?

yes

cat extends animal  // 合理

 

java继承内存布局

以如下代码为例

public class Test {
    public static void main(String[] args) {
    Son son = new Son();
    }
}


class GrandPa {
    String name = "爷爷";
    String hobby = "看黄书";
}

class Father extends GrandPa{
    String name = "爸爸";
    int age = 42;
}

class Son extends Father{
    String name = "儿子";
}

 

Son son = new Son();

的时候

 

第一步,现在方法区加载类的信息,从顶级父类Object开始

 

ps:个人对这个加载顺序的理解为,如果是先从最后的son开始加载,那他是继承前面的父类的,现在父类没加载,他没办法加载完毕自己的,那么就要预留空间,等前面的加载完,再去补充完整自己的,这样的步骤非常琐碎,而且也不知道预留多少空间好,效率低,而从顶级父类开始,在子类加载信息时,直接就能继承过来,一步到位

 

第二步,在堆中开辟Son对象的内存空间,从父类到子类的顺序

 

第三步,返回堆中地址给栈中的son对象引用

 

当Son对象访问一个属性时,按son-->Father-->GrandPa---->Object类的顺序来对着名字找,当找到相同属性名就停止,哪怕Son对象对当前找到的这个属性没有访问权限,也不会再找下去。

posted @ 2022-02-25 11:18  codemelo  阅读(549)  评论(0)    收藏  举报