目录

1、认识继承

​编辑

2、权限修饰符

3、继承的特点

3.1Java中的类为什么不支持多继承?

3.2Java中的祖宗类Object

3.3继承后子类访问成员的特点:就近原则/super讲解

4、方法重写

4.1方法重写的使用场景

5、子类构造器的特点

5.1 子类构造器的应用场景

6、this(...)调用兄弟构造器


        面向对象的三大特征:封装、继承、多态。上篇文章已经介绍过封装了,下面我们来看面向对象另一个重要特征、继承。

1、认识继承

继承是什么?

  • 继承是面向对象编程的核心特性之一
  • 允许一个类(子类)获得另一个类(父类)的属性和方法
  • 实现代码重用和建立类之间的层次关系

         上面的代码有相同的name成员变量,代码大量重复。那么怎么解决代码的重复呢?类的继承。提高代码的重用性,减少一些重复代码的书写。

        Java中提供了一个关键字extends,用这个关键字,可以让一个类和另一个类建立起父子关系。

子类能继承啥?

  • 子类能继承父类的非私有成员(成员变量,成员方法)。

继承后对象的创建

  • 子类的对象是由子类,父类共同完成的

接下来看代码:

People类、父类

//父类
//继承的好处
//1、代码复用性高
//2、减少代码量
public class People {
    private String name;
    private char sex;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public char getSex() {
        return sex;
    }

    public void setSex(char sex) {
        this.sex = sex;
    }
}

Teacher 类、子类

//子类
public class Teacher extends  People {
    private String skill;//技术

    //构造器
    public Teacher(){}
    public Teacher(String skill) {
        this.skill = skill;
    }
    public String getSkill() {
        return skill;
    }

    public void setSkill(String skill) {
        this.skill = skill;
    }
}

Consultant类、子类

//子类
public class Consultant extends  People{
    private int number; //咨询人数
    //构造器
    public Consultant(){}

    public Consultant(String name, char sex, int number) {
        this.number = number;
    }
    public int getNumber() {
        return number;
    }

    public void setNumber(int number) {
        this.number = number;
    }
}

Test类:测试类

//子类
public class Test {
    public static void main(String[] args) {
        //创建老师对象
        //子类可以继承父类的非私有成员
        //子类对象其实是有由子类和多张设计图共同创建出来的对象,所以子类对象是完整的
        Teacher t = new Teacher();
        t.setName("张三");
        t.setSex('男');
        t.setSkill("java");
        System.out.println("姓名:" + t.getName() + " 性别:" + t.getSex() + " 技术:" + t.getSkill());
    }
}

2、权限修饰符

什么是权限修饰符?

就是用来限制类中的成员(成员变量、成员方法、构造器)能够被访问的范围。

3、继承的特点

3.1Java中的类为什么不支持多继承?

3.2Java中的祖宗类Object

  • java中所有的类,要么直接继承了Object,要么默认继承了Object,要么间接继承了Object
  • 因此,Object是所有类的祖宗类

3.3继承后子类访问成员的特点:就近原则/super讲解

  • 在子类方法中访问其他成员变量(成员变量、成员方法),是按照就近原则的。
  • 先子类局部范围找,然后子类成员范围找,然后父类成员范围找,如果父类范围还没有找到就报错。

如果子类中,出现了重名的成员,会优先使用子类的,如果此时一定要在子类中使用父类的怎么办?

可以通过super关键字,指定访问父类的成员:

super.父类成员变量/父类成员方法。

Test类

public class Test {
    public static void main(String[] args) {
        Zi zi = new Zi();
        zi.show();

    }
}
class Fu{
    String name = "fu类的name";
}
class Zi extends Fu{
    String name = "zi类的name";
    public void show(){
        String name = "局部变量";
        System.out.println(name);//打印show方法的 name
        System.out.println(this.name); //打印Zi类的 name
        System.out.println(super.name); //打印Fu类的 name
    }
}

打印结果如下:

继承的特点小结:

4、方法重写

        当子类觉的父类的某个方法不好用,或者无法满足自己的需求时,子类可以重写一个方法名称、参数列表一样的方法,去覆盖父类的这个方法,这就是方法重写。 

        重写小技巧:使用Override注解,他可以指定Java编译器,检查我们方法重写的格式是否正确,代码可读性也更好。

下面看代码了解一下方法重写怎么来实现?

public class Test {
    public static void main(String[] args) {
        Dog newDog = new Dog();
        newDog.cry();//就近访问原则
    }
}

class Dog extends Animal {
    //有时候子类继承父类,父类的方法不能满足子类的需求,这时就需要子类重写父类的方法
    // 方法重写:父类方法名、参数列表必须一致.

    @Override  //方法重写的校验注解(标志):要求方法名、参数列表必须和父类的方法一致。否则报错
    public void cry() {
        System.out.println("汪汪汪~~~");
    }
}

class Animal {
    public void cry() {
        System.out.println("动物会叫~~~");
    }
}

/*代码输出结果:
汪汪汪~~~
 */

注意:方法重写的其它注意事项

  • 子类重写父类方法时,访问权限必须大于或者等于父类该方法的权限(public > protected > 缺省)。
  • 重写的方法返回值类型,必须与重写方法返回值类型一样,或者范围更小
  • 私有方法(私有方法不能被子类继承,所以不能被重写),静态方法不能被重写(静态方法属于类只有一份),如果重写会报错。
  • 在使用的时候一般不会考虑上面的注意事项,但是我们要知道,重写的规范:声明不变,重新实现。

4.1方法重写的使用场景

        方法重写在开发中的常见应用场景:子类重写Object类的toString()方法,以便返回对象的内容

Test类实现上面的场景

public class Test {
    public static void main(String[] args) {
        //方法重写:子类重新Object类的toString()方法,以便于返回对象的内容。
        Student s = new Student("小王", 18, '男');
        System.out.println(s);
        System.out.println(s.toString());
        //注意1:直接输出对象时,默认调用的是Object类的toString()方法,返回对象的地址值。
        //注意2:输出对象的地址实际上没什么意义。在开发中更希望输出对象的内容信息,所以子列类需要重写toString()方法。
        //以便以后输出对象时默认就近调用子类重写的toString方法返回对象内容。
    }
}

class Student{
    private String name;
    private int age;
    private char sex;
    public Student(String name,int age,char sex){
        this.name = name;
        this.age = age;
        this.sex = sex;
    }
    public Student(){}

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public char getSex() {
        return sex;
    }

    public void setSex(char sex) {
        this.sex = sex;
    }
    //重写Object类的toString()方法
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", sex=" + sex +
                '}';
    }
}
/*代码输出结果:
Student{name='小王', age=18, sex=男}
Student{name='小王', age=18, sex=男}
 */

5、子类构造器的特点

        子类的全部构造器,都会先调用父类的构造器再执行自己

Test类:演示上面的的话

public class Test {
    public static void main(String[] args) {
        //子类的全部构造器,都会先调用父类的构造器,再执行自己。
        Zi z = new Zi();
    }
}
class Fu{
    //Fu类的午参构造器
    public Fu(){
        System.out.println("Fu类的无参构造器");
    }
}

class Zi extends Fu{
    public Zi(){
        System.out.println("Zi类的无参构造器");
    }
}
/*代码输出结果:
Fu类的无参构造器
Zi类的无参构造器
 */

 子类构造器是如何实现调用父类构造器的:

  • 默认情况下,子类全部构造器的第一行代码都是super()(写不写都有),它会调用父类的无参数构造器。
  • 如果父类没有无参数构造器,则我们必须在子类构造器的第一行手写super(),指定去调用父类的有参数构造器。

Test类

public class Test {
    public static void main(String[] args) {
        //子类的全部构造器,都会先调用父类的构造器,再执行自己。
        Zi z = new Zi();
    }
}
class Fu{
    //Fu类的午参构造器
    public Fu(int a){
        System.out.println("Fu类的有参构造器");
    }
}

class Zi extends Fu{
    public Zi(){
        super(1);
        System.out.println("Zi类的无参构造器");
    }
}
/*代码输出结果:
Fu类的有参构造器
Zi类的无参构造器
 */

5.1 子类构造器的应用场景

People父类

//父类
//继承的好处
//1、代码复用性高
//2、减少代码量
public class People {
    public People(){}
    public People(String name, char sex) {
        this.name = name;
        this.sex = sex;
    }
    private String name;
    private char sex;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public char getSex() {
        return sex;
    }

    public void setSex(char sex) {
        this.sex = sex;
    }
}

Teacher 子类

public class Teacher extends  People {
    private String skill;//技术

    //构造器
    public Teacher(){}
    public Teacher(String skill, String name, char sex) {
        //调用父类的构造器
        //子类构造器调用父类构造器
        super(name, sex);
        this.skill = skill;
    }
    public String getSkill() {
        return skill;
    }

    public void setSkill(String skill) {
        this.skill = skill;
    }
}

Test测试类

public class Test {
    public static void main(String[] args) {
        //创建老师对象
        //子类可以继承父类的非私有成员
        //子类对象其实是有由子类和多张设计图共同创建出来的对象,所以子类对象是完整的
        Teacher t = new Teacher("java", "张三", '男');
        System.out.println(t.getSkill());
        System.out.println(t.getName());
        System.out.println(t.getSex());
    }
}
/*
输出结果
java
张三
男
 */

6、this(...)调用兄弟构造器

  • 任意类的构造器中,是可以通过this(...)去调用该类的其他构造器。

Student类

public class Student {
    private String name;
    private int age;
    private String schoolName;
    //构造器
    public Student() {
    }
    //如果所以学生的学校名称都是上海大学,那么此时可以使用this(..)调用兄弟构造器
    public Student(String name, int age){
        this(name, age, "上海大学");
    }
    public Student(String name, int age, String schoolName) {
        this.name = name;
        this.age = age;
        this.schoolName = schoolName;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getSchoolName() {
        return schoolName;
    }

    public void setSchoolName(String schoolName) {
        this.schoolName = schoolName;
    }
    //重写toString方法
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", schoolName='" + schoolName + '\'' +
                '}';
    }
}

   Test类测试类 

public class Test {
    public static void main(String[] args) {
        //所有的学生学校名称都是上海大学
        Student s1 = new Student("张三",18);
        Student s2 = new Student("吴京",51);
        System.out.println(s1);
        System.out.println(s2);
    }
}

        注意:this(...)和super(...)都只能放在构造器的第一行,因此,有了this(...)就不能写super(...)l了反之亦然。说白了两者不能同时出现。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐