美文网首页
对Java继承的一些思考-构造函数

对Java继承的一些思考-构造函数

作者: 我啊翔1314 | 来源:发表于2018-07-08 21:31 被阅读0次

    Java的继承,相信对于Java开发者来说,再熟悉不过了。但是如果要深入理解Java的继承,还是需要细细去分析的。所以,我写了这篇博客,记下自己对Java继承的一些理解和思考。

    一、继承的语法

    Java继承主要通过extends关键字实现。其格式如下:

    // 父类Animal类
    public class Animal {
    
    }
    
    // 子类Dog类,继承自Animal类
    public class Dog extends Animal {
    
    }
    

    继承的语法十分简洁。继承了父类以后,子类就拥有父类的一些特性了。

    二、构造函数

    构造函数是类实例化的入口,Java的构造函数,与类名同名:

    public class Animal {
      // 构造函数
      public Animal(Sting name) {
      }
    }
    

    另外,Java类的构造函数支持重载:

    public class Animal {
      public Animal(String name) {
        this(name, "男");
      }
    
      public Animal(String name, String sex) {
        System.out.println(name + "," + sex);
      }
    }
    

    子类要在构造函数中调用父类的构造函数,可使用super关键字:

    public class Dog extends Animal {
      public Dog(String name, String sex, String type) {
        super(name, sex);
        System.out.println(type);
      }
    }
    

    子类必须直接或者间接调用父类的构造函数,间接调用是指用this调用自身构造函数,而this指向的构造函数已调用父类的构造函数:

    public class Dog extends Animal {
      public Dog(String name, String sex) {
        // 间接调用父类构造函数
        this(name, sex, "金毛");
      }
    
      public Dog(String name, String sex, String type) {
        // 直接调用构造函数
        super(name, sex);
        System.out.println(type);
      }
    }
    

    在这里也许会有一个疑问,平时写继承的时候,我们不写构造函数,Java编译器也不会报错,像下面这个例子:

    public class Dictionary extends Book {
      public void nextPage() {
      }
    }
    // 程序不报错
    new Dictionary()
    

    这是为什么呢?
    其实,在类中如果没有写构造函数,Java会默认添加一个无参构造函数,如果这个类没有继承其他类,则该构造函数时一个空的构造函数;如果这个类继承自其它类,那么还会在该构造函数中添加super()。因此,上述例子实际上等价于如下代码:

    public class Dictionary extends Book {
      // 没有构造函数时,Java自动添加
      public Dictionary() {
        super();
      }
    
      public void nextPage() {
      }
    }
    new Dictionary()
    

    既然可以调用super()。那么可以推断出,父类一定也有一个无参构造函数:

    public class Book {
      public Book() {
        // coding...
      }
      ...
    }
    

    或者不写构造函数,原理与其子类相同

    public class Book {
      // 没有构造函数时,Java会自动添加一个无参构造函数
      ...
    }
    

    因此,在没有写构造函数的情况下,子类构造函数的创建以及父类构造函数的调用由Java自动完成了。
    此外,子类的构造函数如果没有直接或间接调用父类构造函数,那么Java编译器会在该构造函数中自动添加super();

    public class Animal {
      public Animal() {
        System.out.println("动物");
      }
    }
    
    public class Dog extends Animal {
      public Dog() {
        // 如果在子类构造函数中没有直接或间接调用父类构造函数,
        // 那么Java会在构造函数中自动添加super();
        // super();
        System.out.println("狗");
      }
      public Dog(String name, String sex) {
        // super();
        System.out.println(name + "," + sex);
      }
      new Dog();
      new Dog("LiHua","女");
    }
    

    上述代码执行以后,打印的结果为:

    动物
    狗
    动物
    LiHua,女
    

    可以看出,大部分情况下,我们就算不写构造函数,Java编译器依然不会报错,因为Java会自动为类添加默认的构造函数。但是,某些条件下,不写会出现问题,请看下面的例子:

    public class Animal {
      public Animal(String name) {
        System.out.println("动物");
      }
    }
    
    public class Dog extends Animal{
      public Dog() {
        System.out.println("狗");
      }
    }
    
    new Dog();
    

    这时,编译器就会报错

    Exception in thread "main" java.lang.NoSuchMethodError:Animal:method<init>()V not found
    

    那么,此时为什么会报错呢?
    因为子类如果没有直接或间接调用父类构造函数时,Java会在子类构造函数自动添加super(),即调用父类无参构造函数;但是在本例子中,父类的构造函数并没有无参构造函数:

    public class Animal {
      public Animal(String name) {
        System.out.println("动物");
      }
    }
    

    有人会问,Java不是会自动为Animal类添加一个无参构造函数吗?
    因为在Animal类中已经有构造函数,只有在类中没有写构造函数的情况下,Java才会自动为类添加一个无参构造函数。
    要解决上述错误,那么就要在子类显示调用父类构造函数:

    public class Dog extends Animal {
      public Dog() {
        super("");
        System.out.println("狗");
      }
    }
    

    或者在父类添加无参构造函数:

    public class Animal {
      public Animal() {
        System.out.println("动物");
      }
      
      public Animal(String name) {
        System.out.println("动物");
      }
    }
    

    相关文章

      网友评论

          本文标题:对Java继承的一些思考-构造函数

          本文链接:https://www.haomeiwen.com/subject/hfrouftx.html