Java的继承

Java的继承

继承的本质是对某一批类的抽象。用extends关键字,子类(派生类)是父类(基类)的扩展。

  1. Object类:Java中,无论写不写entents Object类,所有的类都默认直接或间接继承Object类。

  2. super:可以和this关键字对比。this是本身调用者这个对象(无继承关系时也可以使用),super是指向父类对象的引用(只能在有继承关系时使用)。

  3. 方法重写(和重载不同意义):重写都是针对的方法,属性没有重写的说法。

继承

  1. 子类继承父类,会拥有父类的全部public属性全部public方法

  2. 子类继承父类,不会拥有父类的private属性private方法

  3. Java的继承是单继承:一个儿子,只能有一个父亲;一个父类,可以用多个子类。

举例:

1、Person类(父类):

package com.WZ.Demo.ClassSet;
public class Person {
   public int age = 5;
   public int getAge(){
       return this.age;
  }
}

2、Student类(子类):

package com.WZ.Demo.ClassSet;
public class Student extends Person { }

3、main()方法:

package com.WZ.Demo.Application;
import com.WZ.Demo.ClassSet.Student;
public class Application {
   public static void main(String[] args) {
       Student student = new Student();
       System.out.println( student.getAge());
  }
}

输出:5

查看继承关系结构

鼠标点击在类名上,然后Ctrl + H。就可以看到该类的继承关系。

Java中,无论写不写entents Object类,所有的类都默认直接或间接继承Object类。所以,上图中Person类上面有个Object类。

Super调用:属性和方法

this:调用的当前对象的

super:调用的父代对象的

1、父类:

package com.WZ.Demo.ClassSet;
public class Person {
   public String name = "父代";
   public void getName(){
       System.out.println("输出的是:父代");;
  }
}

2、子类:

package com.WZ.Demo.ClassSet;
public class Student extends Person {
   public String name = "子代";
   public void getName(){
       System.out.println("输出的是:子代");;
  }
   public void test(String name)
  {
       System.out.println(name);          //输出:Wang Zan,传进来的参数
       System.out.println(this.name);     //输出:子代,当前的属性值
       System.out.println(super.name);    //输出:父代,父代的属性值
       this.getName();                    //调用了当前的方法
       super.getName();                   //调用了父代的方法
  }
}

3、main()方法

package com.WZ.Demo.Application;
import com.WZ.Demo.ClassSet.Student;
public class Application {
   public static void main(String[] args) {
       Student student = new Student();
       student.test("Wang Zan");
  }
}

输出:

Wang Zan 子代 父代 输出的是:子代 输出的是:父代

Super调用:构造器

super:调用的是父代的构造器。

super和this不能同时调用构造方法,因为两个都要在第一行。

注意:

  1. 当父代的构造器是有参构造,没有显示的写无参构造,在子代不能调用父代的无参构造器。

  1. 创建子代对象:

2.1. 父代和子代都不写有参构造时:用无参构造创建对象,自动调用父代和子代的无参构造

2.2. 父代和子代都写有参构造时:用有参构造创建对象,自动调用父代的无参构造和子代的有参构造

1、父类:

package com.WZ.Demo.ClassSet;
public class Person {
   public Person() {
       System.out.println("调用了父代的无参构造器");
  }
   public Person(int a) {
       System.out.println("调用了父代的有参构造器");
  }
}

2、子类:

package com.WZ.Demo.ClassSet;
public class Student extends Person {
   public Student() {
       System.out.println("调用了子代的无参构造器");
  }
   public Student(int a) {
       System.out.println("调用了子代的有参构造器");
  }
}

3、main()方法

package com.WZ.Demo.Application;
import com.WZ.Demo.ClassSet.Student;
public class Application {
   public static void main(String[] args) {
       //用无参构造创建对象,自动调用父代和子代的无参构造
       Student student1 = new Student();
       System.out.println("===================");
       //用有参构造创建对象,自动调用父代的无参构造和子代的有参构造
       Student student2 = new Student(3);
  }
}

输出:

调用了父代的无参构造器 调用了子代的无参构造器

=================== 调用了父代的无参构造器 调用了子代的有参构造器

上例中,输出调用了父代的无参构造器原因:

字类的构造器中,有个隐藏代码super(),它会自动调用父代的无参构造器。

且如果显示的写super()调用父类的构造器,必须写在子类构造器的第一行,否则报错。(super()可以不写,Java会默认调用)

下面两个子代写法等效:

写法1:显示写上super()

package com.WZ.Demo.ClassSet;
public class Student extends Person {
   public Student() {
       super();
       System.out.println("调用了子代的无参构造器");
  }
}

写法2:不写super()

package com.WZ.Demo.ClassSet;
public class Student extends Person {
   public Student() {
       System.out.println("调用了子代的无参构造器");
  }
}

父类和子类关于有参构造和无参构造最重要的一句话:只要写了有参构造,无论无参构造有没有用,都显示写上

父类只写有参,不显示写无参:子类也无法用无参方法进行构造

举例:

 

方法重写(和重载不是一个意思)

  1. 重写是方法的重写。针对的是父类功能子类不一定需要,或者不一定满足的时候,需要重写。

  2. 属性没有重写的概念

  3. 重写只与非静态方法有关(无static关键字)

  4. 重写的只能是public方法,private方法不能重写

  5. 重写需要有继承关系,是子类重写父类的方法。  

            5.1. 方法名必须相同,方法体不同

            5.2. 参数列表必须相同(否则就是重载了)

            5.3. 修饰符,范围可以扩大,但不能缩小:public > protected > Default > private

            5.4. 抛出异常:范围可以被缩小,但不能扩大:ClassNotFoundException ---> Exception(大)

static方法的子类和父类调用特点

static方法的调用,只和等号左侧有关,与右边new的数据无关

解释下:

A a = new A();

B b = new A();

B是父代,A是子代,创建对象后,a调用的是a自己的static方法,b调用的是b自己的static方法。

所以输出:"B=>test()" 和"A=>test()"

1、父代

package com.WZ.Demo.ClassSet;
public class B {
   public static void test_static() {
       System.out.println("B=>test()");
  }
}

2、子代

package com.WZ.Demo.ClassSet;
public class A extends B {
   public static void test_static() {
       System.out.println("A=>test()");
  }
}

3、main()

 com.WZ.Demo.Application;

import com.WZ.Demo.ClassSet.A;
import com.WZ.Demo.ClassSet.B;

public class Application {
   public static void main(String[] args) {
       A a = new A();
       a.test_static();  //输出:A=>test()

       //父类的引用指向了子类
       B b = new A();
       b.test_static();  //输出:B=>test()

输出:

A=>test() B=>test()

非static方法的子类和父类调用特点(上例中,父类和子类方法都去掉static)

首选,与static方法(静态方法)不同,非静态方法中,子类重写了父类方法,调用方法时,就调用自己的方法了。

简而言之:子类重写了父类的方法时,当用子类new了个对象,该对象调用的是子类的方法。

解释下:

A a = new A();

B b = new A();

B是父代,A是子代,创建对象后,a调用的是a自己的方法,b调用的也是a的方法

所以输出:"A=>test()" 和"A=>test()"

完整代码如下:

1、父代

package com.WZ.Demo.ClassSet;
public class B {
   public void test_static() {
       System.out.println("B=>test()");
  }
}

2、子代

package com.WZ.Demo.ClassSet;
public class A extends B {
   public void test_static() {
       System.out.println("A=>test()");
  }
}

3、main()

package com.WZ.Demo.Application;
import com.WZ.Demo.ClassSet.A;
import com.WZ.Demo.ClassSet.B;
public class Application {
   public static void main(String[] args) {
       A a = new A();
       a.test_static();  //输出:A=>test()
       //父类的引用指向了子类
       B b = new A();
       b.test_static();  //输出:A=>test()
  }
}

输出:

A=>test()

A=>test()

关于方法的重写(在子类中,采用Alt+Insert,可以Override Methods):

  1. 若在子类中,不重写父类方法,只是导入Override Methods,子类自动继承父类方法(super.test_static())。

package com.WZ.Demo.ClassSet;
public class A extends B {
    @Override
   public void test_static() {
       super.test_static();
  }
}
  1. 若在子类中,重写父类方法,先删除子类自动继承父类方法(super.test_static()),然后重写。

package com.WZ.Demo.ClassSet;
public class A extends B {
    @Override
   public void test_static() {
       System.out.println("A=>test()");
  }
}

第一种情况的完整代码如下:

1、父代

package com.WZ.Demo.ClassSet;
public class B {
   public void test_static() {
       System.out.println("B=>test()");
  }
}

2、子代

package com.WZ.Demo.ClassSet;
public class A extends B {
    @Override
   public void test_static() {
       super.test_static();
  }
}

3、main()

 com.WZ.Demo.Application;

import com.WZ.Demo.ClassSet.A;
import com.WZ.Demo.ClassSet.B;

public class Application {
   public static void main(String[] args) {
       A a = new A();
       a.test_static();  //输出:B=>test()

       //父类的引用指向了子类
       B b = new A();
       b.test_static();  //输出:B=>test()

输出:

B=>test()

B=>test()

第二种情况的完整代码如下:

1、父代

package com.WZ.Demo.ClassSet;
public class B {
   public void test_static() {
       System.out.println("B=>test()");
  }
}

2、子代

package com.WZ.Demo.ClassSet;
public class A extends B {
   @Override
   public void test_static() {
       System.out.println("A=>test()");
  }
}

3、main()

package com.WZ.Demo.Application;
import com.WZ.Demo.ClassSet.A;
import com.WZ.Demo.ClassSet.B;
public class Application {
   public static void main(String[] args) {
       A a = new A();
       a.test_static();  //输出:A=>test()
       //父类的引用指向了子类
       B b = new A();
       b.test_static();  //输出:A=>test()
  }
}

输出:

A=>test()

A=>test()

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2020-02-12 23:59  WZ_BeiHang  阅读(205)  评论(0)    收藏  举报