zoukankan      html  css  js  c++  java
  • Java继承

    继承介绍

    在java语言中,类可以从其他类继承而来,并继承父类的成员和方法。

    继承是简单但是非常强大:当你需要创建一个新类,但是已经有其他类,它已经包含了一些你需要的代码,那么你可以从已有的这个类,继承新的类。这样,你不用写重复的代码和调试,就可以重用已有类的成员和方法。

    子类从父类继承所有的成员(变量,方法和内部类),构造方法不是成员,所以不会被继承,但是子类的构造方法可以调用父类的构造方法。

    在java平台中,java.lang.Object是所有类的父类,有些类直接继承Object,有些类间继承其他类,其他类继承自Object。

    继承例子

    Bicycle类

    复制代码
    public class Bicycle {

    // the Bicycle class has
    // three fields
    public int cadence;
    public int gear;
    public int speed;

    // the Bicycle class has
    // one constructor
    public Bicycle(int startCadence, int startSpeed, int startGear) {
    gear
    = startGear;
    cadence
    = startCadence;
    speed
    = startSpeed;
    }

    // the Bicycle class has
    // four methods
    public void setCadence(int newValue) {
    cadence
    = newValue;
    }

    public void setGear(int newValue) {
    gear
    = newValue;
    }

    public void applyBrake(int decrement) {
    speed
    -= decrement;
    }

    public void speedUp(int increment) {
    speed
    += increment;
    }

    }
    复制代码

    一个类MountainBike类继承自Bicycle:

    复制代码
    public class MountainBike extends Bicycle {

    // the MountainBike subclass adds
    // one field
    public int seatHeight;

    // the MountainBike subclass has one
    // constructor
    public MountainBike(int startHeight,
    int startCadence,
    int startSpeed,
    int startGear) {
    super(startCadence, startSpeed, startGear);
    seatHeight
    = startHeight;
    }

    // the MountainBike subclass adds
    // one method
    public void setHeight(int newValue) {
    seatHeight
    = newValue;
    }
    }
    复制代码

    MountainBike继承Bicycle的所有变量和方法,并添加了seatHeight变量和对应的set方法。MountainBike新类,它有四个变量和五个方法,不过你未必要全部都要使用。

    如果Bicycle的方法很复杂,并已经使用了大量的时间调试,那么这种复用代码的方式,是相当简单并有价值。

     

    子类能做的事情

    子类继承父类所有的public和protected成员,不管父类在哪个包。如果子类和父类在同一个包,它也会继承父类的 package-private成员(没有修饰public,privat,protected的成员),对于继承的成员,可以替换它,隐藏它,或者补充 新成员:

    1.被继承的成员变量可以直接使用,就像使用其他成员

    2.声明一个新成员变量,名字和父类的成员变量名字一样,就隐藏了该成员(不推荐)

    3.声明不存在父类的新成员变量。

    4.继承的方法可以直接使用

    5.在子类实现一个与父类签名一样的方法,可以覆盖父类的方法。

    6.在子类实现一个与父类签名一样的新的static方法,可以覆盖父类的方法。

    7.可以声明一个不存在父类的新成员方法。

    8.实现一个子类的构造器,通过隐式或者显示使用super调用父类的构造器。

    父类的private成员

    子类不会继承父类的private成员,但是,如果父类已经有public或protected方法访问的私有成员,那么通过可以继承的方法,依然可以间接访问父类的private成员.

    内部类可以访问嵌套类的所有成员,包括嵌套类private成员。

    对象转换

    一个对象的实例化,我们可能这么写:

    public MountainBike myBike = new MountainBike();

    这表示myBike是MountainBike类型。

    MountainBike派生自BicycleObject,所以,一个MountainBike实例既是一个Bicycle,也是一个Object.

    而逆转的未必是可以的:一个Bicycle未必是MountainBike。同样的,一个Object未必是Bicycle或者MountainBike。

    类型转换显示在允许的继承和实现中,一个对象,从一种类型替换为另一种类型的用法.例如

    Object obj = new MountainBike();

    这样obj既是一个Object,也是一个Mountainbike。

    另一边,我们这么写:

    MountainBike myBike = obj;

    我们会遇到一个编译时错误,因为对于obj,编译器不知道它是一个MountainBike。尽管如此,我们可以告诉编译器,通过显示转换,将obj转换为类型MountainBike

    MountainBike myBike = (MountainBike)obj;

    这种转换为插入一个运行时检测,编译器会安全假设obj是一个MountainBike类型,但如果obj不是一个MountainBike,运行时,会抛出异常。

    当然,你可以使用instanceof操作符做逻辑测试,判断obj是否MountainBike类型再做转换

    if (obj instanceof MountainBike) {
    MountainBike myBike
    = (MountainBike)obj;
    }

    这样,我们做类型转换,就不会有运行时异常抛出了。

     

    继承中属性、方法和对象的关系

        大家都知道子类继承父类是类型的继承,包括属性和方法!如果子类和父类中的方法签名相同就叫覆盖!如果子类和父类的属性相同,父类就会隐藏自己的属性!

    但是如果我用父类和子类所创建的引用指向子类所创建的对象,父类引用所调用子类对象中的属性值或方法的结果是什么呢?

    看代码:

    复制代码
    public class FieldDemo {  
    public static void main(String[] args){
    Student t
    = new Student("Jack");
    Person p
    = t;//父类创建的引用指向子类所创建的对象
    System.out.println(t.name+","+p.name);
    System.out.println(t.getName()
    +","+p.getName());
    }

    }
    class Person{
    String name;
    int age;
    public String getName(){
    return this.name;
    }
    }
    class Student extends Person{
    String name;
    // 属性和父类属性名相同,但在做开发时一般不会和父类属性名相同!!
    public Student(String name){
    this.name = name;
    super.name = "Rose"; // 为父类中的属性赋值
    }
    public String getName(){
    return this.name;
    }
    }
    复制代码

    返回结果是:Jack,Rose
    Jack,Jack

    原因是:在Java中,属性绑定到类型,方法绑定到对象!

    内存图如下:

    关于JAVA继承类的静态变量、成员变量、父子类构造方法调用顺序的探讨 .

    综合网上的相关帖子和我自己的调试,研究了一下关于JAVA继承类的静态变量、成员变量、父子类构造方法调用顺序问题。首先看一段程序:

    class X {
        Y b
    =new Y();//7、这里是父类成员变量初始化
        static Y sb=new Y();//1、父类静态变量,输出static Y(静态代码块先初始化),2、Y

       
    static{
            System.out.println(
    "static X父类静态代码块");//3、执行静态代码块
            new Y();//4、这里只是输出Y,有static Y(静态代码块只执行一次)
        }
        X() {

            System.out.println("X");//8、父类成员变量初始化之后,执行父类构造器输出X
        }
    }

    class Y {
       
    static{
            System.out.println(
    "static Y");       
        }
        Y() {
    //执行构造函数
           
    //这里有个super()==Object()
            System.out.println("Y");
        }
    }

    publicclass Z extends X {
       
    finalstaticint mead=45;
       
    finalbyte b=16;
       
    static Y sb=new Y();//5、子类的静态变量,输出Y
        static{      
            System.out.println(
    "static Z");//6、子类的静态代码块
        }
        Y y
    =new Y();//9、这里是子类成员变量初始化

        Z() {
           
    //这里有super()==new X()
            this.y =null;
            System.out.println(
    "Z");//10、子类成员变量初始化之后,执行子类构造器输出Z
        }

       
    publicstaticvoid main(String[] args) {
           
    new Z();

        }
    }

    执行结果:

    static Y
    Y
    static X父类静态代码块
    Y
    Y
    static Z
    Y
    X
    Y
    Z

    解释:
    static的东西在编译的时候就向内存要到了存取空间,他们的初始化要早于非static,顺序是先父类再子类。
    初始化类,先执行super()父类的的构造函数(final和static之后),父类的构造函数先执行super()直到object super(),完了执行一般成员变量的初始化

    一般成员变量初始化完毕,执行构造器里面的代码(super()之后的代码).
    父类的初始化完成后(子类构造器里面super执行完毕),才轮到子类的成员变量初始化
    子类成员变量初始化完毕,开始执行子类构造器里面的代码(super()之后的代码).

    注意:

    静态块和静态变量的调用顺序是按照书写顺序执行的,比如上边X类中静态块和静态变量的书写顺序颠倒如下:

    class X {
      Y b = new Y();
           static{
            System.out.println("static X父类静态代码块");
            new Y();
        }
        static Y sb= new Y();
        X() {
            System.out.println("X");
        }
      
    }

    则执行结果为:

    static X父类静态代码块
    static Y
    Y
    Y
    Y
    static Z
    Y
    X
    Y
    Z

    最后:

    确定变量空间和初始化赋值是分开进行的,先一次性确定静态成员变量空间 并赋给二进制0 ,然后按照书写顺序逐一赋值

    如下代码,输出结果是0.0

    publicclass Test {
       
    staticint i=f();
       
    staticdouble d=0.1234;
       
    publicstaticvoid main(String[] args) {
           
    new Test();
        }
       
    staticint f(){
            System.out.println(d);
           
    return3;
        }
    }

    原址:

    http://blog.csdn.net/pisota/article/details/5332848


  • 相关阅读:
    085 Maximal Rectangle 最大矩形
    084 Largest Rectangle in Histogram 柱状图中最大的矩形
    083 Remove Duplicates from Sorted List 有序链表中删除重复的结点
    082 Remove Duplicates from Sorted List II 有序的链表删除重复的结点 II
    081 Search in Rotated Sorted Array II 搜索旋转排序数组 ||
    080 Remove Duplicates from Sorted Array II 从排序阵列中删除重复 II
    079 Word Search 单词搜索
    078 Subsets 子集
    bzoj2326: [HNOI2011]数学作业
    bzoj2152: 聪聪可可
  • 原文地址:https://www.cnblogs.com/biggestfish/p/2916817.html
Copyright © 2011-2022 走看看