Java基础——继承,我继承了什么

2017-06-18  本文已影响140人  阿敏其人

类的继承格式

class 父类 {
}
class 子类 extends 父类 {
}

通过extends关键字来实现

一、为什么需要继承

有一些类有共同的地方,容易出现代码冗余,所以我们需要抽取一下,封装继承多态嘛。

子类通过复写方法等方式可以对父类做一些拓展,比如:
笔都有产地和颜色,笔就是父类,钢笔继承自笔,钢笔的产地和颜色是什么,蜡笔呢,毛笔也有,但是毛笔没有笔帽,特殊一点,这就可以做拓展了,为什么没有笔帽,要注意什么。

二、继承到底继承了什么?有什么特点?

一个类里面有4种东西

子类继承父类的时候,到底继承了什么?

对于private这点非常好理解,因为private的访问权限是本类中嘛,就算通过super也不能访问private的private属性。但是可以通过对应的get方法获取,get是public嘛。

如果子类非要访问父类的私有域,那么就反射吧

继承有什么特点:

三、子类的初始化

类的初始化分为 类初始化 和 对象初始化。

三、1.类初始化

先执行父类的 类成员(static成员) 和 类代码块(static代码块),后执行子类的类成员(static成员) 和 类代码块(static代码块)。

static成员和static代码块仅会在类加载的时候加载一次。

三、2.对象初始化

1、先初始化父类的属性和代码块,后初始化子类的属性和代码块。
2、接着初始化父类的构造函数,然后是子类

关于子类能从父类继承到什么和继承中的类初始化,我们看一下下面的代码就清楚了:

AClass

public class AClass {
    int normalVar = 10;
    // 父类私有变量,子类无法继承,但可以get到
    private int priVar = 20;
    {
        System.out.println("AClass 普通代码块");
    }
    
    static{
        System.out.println("AClass static代码块");
    }
    
    public AClass(){
        System.out.println("AClass 无参构造方法");
    }
    
    public AClass(String str){
        System.out.println("AClass 带参构造方法!");
        
    }
    public void aMethodOne(){
        normalVar = 55;
        System.out.println("aMethodOne");
    }
    
    public void aMethodTwo(){
        normalVar = 66;
        System.out.println("aMethodTwo");
    }
    
    public int getPriVar() {
        return priVar;
    }
    
    public void setNormalVar(int normalVar) {
        this.normalVar = normalVar;
    }
}

.
.
BClass

public class BClass extends AClass{
    {
        System.out.println("BClass 普通代码块");
    }
    
    static{
        System.out.println("BClass static代码块");
    }
    

    public BClass(){
        System.out.println("BClass 无参构造方法");
    }
    
    public BClass(String str){
        System.out.println("BClass 带参构造方法!");
    }
    
    @Override
    public void aMethodOne() {
        super.aMethodOne();
        System.out.println("子类Override的aMethodOne方法 并且调用super.aMethodOne();");
    }

    @Override
    public void aMethodTwo() {
        //super.aMethodTwo();
        System.out.println("子类Override的aMethodTwo方法 不调用super.aMethodTwo();");
    }
    
    public void getFatherVar(){
        System.out.println("调用父类的非私有变量:"+normalVar);
        //int a = priVar; // 父类的私有变量子类无法继承,本句会报错
    }
}

.
.
TrtExt

public class TrtExt{
    public static void main(String[] args) {
        BClass bClass1 = new BClass();
        
        System.out.println("=========");
        BClass bClassZs = new BClass("张三"); 
        bClassZs.getFatherVar();
        bClassZs.setNormalVar(88); // 子类bClass2对象改变父类的变量,不会影响其他子类
        
        System.out.println("====================");
        BClass bClassLs = new BClass("李四"); 
        bClassLs.getFatherVar();// 
        
        System.out.println("====================");
        BClass bClassWw = new BClass("王五"); 
        bClassWw.getFatherVar();// 父类的原始值
        bClassWw.aMethodOne(); // BClass的aMethodOne方法有super.aMethodOne();所以会调父类的aMethodOne()
        bClassWw.getFatherVar();
        
        System.out.println("====================");
        BClass bClassAl = new BClass("阿六"); 
        bClassAl.getFatherVar();//  父类的原始值
        bClassAl.aMethodTwo();// BClass的aMethodTwo方法 没有super.aMethodOne();所以不调父类aMethodTwo
        bClassAl.getFatherVar();
    }
}

.
.
输出:

AClass static代码块
BClass static代码块
AClass 普通代码块
AClass 无参构造方法
BClass 普通代码块
BClass 无参构造方法
=========
AClass 普通代码块
AClass 无参构造方法
BClass 普通代码块
BClass 带参构造方法!
调用父类的非私有变量:10
====================
AClass 普通代码块
AClass 无参构造方法
BClass 普通代码块
BClass 带参构造方法!
调用父类的非私有变量:10
====================
AClass 普通代码块
AClass 无参构造方法
BClass 普通代码块
BClass 带参构造方法!
调用父类的非私有变量:10
aMethodOne
子类Override的aMethodOne方法 并且调用super.aMethodOne();
调用父类的非私有变量:55
====================
AClass 普通代码块
AClass 无参构造方法
BClass 普通代码块
BClass 带参构造方法!
调用父类的非私有变量:10
子类Override的aMethodTwo方法 不调用super.aMethodTwo();
调用父类的非私有变量:10

通过这个例子,我们可以清楚地看到

四、overload和override

方法重载(overload)
1.必须是同一个类
2方法名一样
3参数类型不一样或参数数量不一样

方法的重写/复写(override)

子类对父类方法的复写

两同两小一大原则:

两同:
方法名相同,参数类型相同

两小:
子类返回类型小于等于父类方法返回类型,若为基本类型或者void则必须相同
子类抛出异常小于等于父类方法抛出异常,

一大:
子类访问权限大于等于父类方法访问权限。

实例一下:

AClass

public class AClass {
    public int number = 10;
    protected void changeNumber(int i){
        setNumber(100);
        System.out.println("父类 changeNumber:  "+number);
        
    }
    
    public int setNumber(int i) {
        number = i;
        System.out.println("父类 number:  "+number);
        return number;
    }
}

.
.
BClass

public class BClass extends AClass{

    // 这个复写方法的访问权限比父类大,也就是两者访问权限不一致,但是也是对那个方法的复写
    @Override
    public void changeNumber(int i) {
        super.changeNumber(i);
        setNumber(i);
    }
}

.
.
TrtExt

public class TrtExt{
    public static void main(String[] args) {
        BClass bClass2 = new BClass(); 
        bClass2.changeNumber(70);
    }
}

输出:


父类 number:  100
父类 changeNumber:  100
父类 number:  70

我们看到,其实并不是复写的方法就需要和父类方法完全一致的。

上一篇下一篇

猜你喜欢

热点阅读