Java(十七)继承

简介: Java(十七)继承

继承是面向对象的三大特点之一。


那么,何为继承?


一个类的对象可以使用另一个类的对象中的成员,这种关系就称之为继承。

 

一:继承格式


继承关键字extends。


/**
 * 人类
 */
class person
{
}
/**
 * 学生类
 */
class student extends person
{
}

 

二:继承的优缺点


优点

1:提高了代码的复用性


2:让类与类之间产生了继承的关系,这是构成多态的前提条件。


3:减少代码冗余,增强类的功能扩展性。


缺点

提高了代码的耦合性。在开发中我们遵循:高内聚,低耦合的原则。


高内聚:指一个类的功能越强越好


低耦合:指一个类的关系越少越好

 

三:继承的特点


1:java只支持单继承,不可以多继承。


/**
 * 父亲类
 */
class fu
{
}
/**
 * 儿子类
 */
class zi extends fu
{
}

 

2:java类可以多层继承

/**
 * 爷爷类
 */
class ye
{
}
/**
 * 父亲类
 */
class fu extends ye
{
}
/**
 * 儿子类
 */
class zi extends fu
{
}

 

3:java类不支持循环继承


/**
 * 爷爷类
 */
class ye extends zi
{
}
/**
 * 父亲类
 */
class fu extends ye
{
}
/**
 * 儿子类
 */
class zi extends fu
{
}

这样写是不可以的。

 

四:继承后:成员变量、成员方法的访问特点


1:子类不能继承父类中被private关键字所修饰的成员变量和成员方法。


2:子类不能继承父类的构造方法。


3:在子类方法中访问成员(成员变量、成员方法)满足:就近原则,先子类局部范围找 然后子类成员范围找 然后父类成员范围找,如果父类范围还没有找到则报错。


如果子父类中,出现了重名的成员,会优先使用子类的,此时如果一定要在子类中使用父类的怎么办? 可以通过super关键字,指定访问父类的成员。

 

五:方法重写


Java子类重写父类方法标识:@Override


重写方法的名称、形参列表必须与被重写方法的名称和参数列表一致。


私有方法不能被重写。


子类重写父类方法时,访问权限必须大于或者等于父类 (暂时了解 :缺省 < protected < public)


子类写一个与父类申明一样的方法覆盖父类的方法。 @Override注解可以校验重写是否正确,同时可读性好。


重写方法的名称和形参列表应该与被重写方法一致。 私有方法不能被重写。


重写父类的静态方法会报错的。


public class T06 {
    public static void main(String[] args) {
        person fu = new person();
        student stu = new student();
        fu.drink();
        stu.drink();
    }
}
/**
 * 人类
 */
class person
{
    public void drink()
    {
        System.out.println("父类喝水");
    }
}
/**
 * 学生类
 */
class student extends person
{
    @Override
    public void drink()
    {
        System.out.println("子类喝水");
    }
}


输出:

父类喝水

子类喝水

 

六:this、super关键字


关键字 访问成员变量 访问成员方法 访问构造方法
this this.成员变量 访问本类成员变量 this.成员方法(…) 访问本类成员方法 this(…)访问本类构造方法
super super.成员变量 访问父类成员变量 super.成员方法(…) 访问父类成员方法 super(…) 访问父类构造方法


我们先来看下方的代码:


package d0131;
public class T05 {
    public static void main(String[] args) {
        student stu = new student();
        stu.drink();
    }
}
/**
 * 人类
 */
class person
{
    public int i = 1;
    public void drink()
    {
        System.out.println("父类喝水");
    }
}
/**
 * 学生类
 */
class student extends person
{
    int i = 2;
    @Override
    public void drink()
    {
        int i = 3;
        System.out.println(i);
        System.out.println(i);
        System.out.println(i);
    }
}

控制台输出:

3

3

3

那现在有一个小要求,要求控制台输出3/2/1,我们该如何实现呢?


这其中就需要使用到this以及super关键字。


代码如下所示:


public class T05 {
    public static void main(String[] args) {
        student stu = new student();
        stu.drink();
    }
}
/**
 * 人类
 */
class person
{
    public int i = 1;
    public void drink()
    {
        System.out.println("父类喝水");
    }
}
/**
 * 学生类
 */
class student extends person
{
    int i = 2;
    @Override
    public void drink()
    {
        int i = 3;
        System.out.println(i);
        // 当前这个类的成员变量i
        System.out.println(this.i);
        // 父类的成员变量i
        System.out.println(super.i);
    }
}

输出:

3

2

1

七:构造函数


1:子类的构造函数中,默认都加载了一次父类的构造函数,也就是super()


public class T01 {
    public static void main(String[] args) {
        zi zi1 = new zi();
        zi zi2 = new zi("xh");
    }
}
class fu
{
    public fu()
    {
        System.out.println("我被调用了!");
    }
    private String files;
    public String getFiles() {
        return files;
    }
    public void setFiles(String files) {
        this.files = files;
    }
}
class zi extends fu
{
    /**
     * 无参构造方法
     */
    public zi()
    {
        // 默认就有一个super方法
        // super();
    }
    /**
     * 重载有参构造方法
     * @param name
     */
    public zi(String name)
    {
        // 默认就有一个super方法
        // super();
    }
}

上边的程序,控制台输出:

我被调用了!

我被调用了!

 

为什么会有这样的现象呢?


因为有继承,说明子类可以使用父类的成员变量,那也就意味着父类的成员变量一定要有一直才可以被使用,所以在创建类对象的时候,会调用子类的构造方法,而子类的构造方法中会先去调用父类的构造方法,目的就是给父类的额成员变量默认初始化

 

2:子类的所有构造方法中,第一行要么是super(参数),要么是this(参数),他们不可以共存。并且子类中所有的构造方法中至少有一个构造方法里边调用的是super(参数)


class zi extends fu
{
    /**
     * 无参构造方法
     */
    public zi()
    {
        // 默认就有一个super方法
        // super();
        this("xxx");
    }
    /**
     * 重载有参构造方法
     * @param name
     */
    public zi(String name)
    {
        // 默认就有一个super方法
        // super();
        this();
    }
}

这样写是不行的。编译报错。死循环了属于是。

 

以上大概就是 java 继承的基本使用。

 

有好的建议,请在下方输入你的评论。


目录
相关文章
|
3月前
|
Java 程序员
Java中的继承和多态:理解面向对象编程的核心概念
【8月更文挑战第22天】在Java的世界中,继承和多态不仅仅是编程技巧,它们是构建可维护、可扩展软件架构的基石。通过本文,我们将深入探讨这两个概念,并揭示它们如何共同作用于面向对象编程(OOP)的实践之中。你将了解继承如何简化代码重用,以及多态如何为程序提供灵活性和扩展性。让我们启程,探索Java语言中这些强大特性的秘密。
|
20天前
|
Java 开发者
在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口
【10月更文挑战第20天】在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口。本文揭示了这两种方式的微妙差异和潜在陷阱,帮助你更好地理解和选择适合项目需求的线程创建方式。
15 3
|
20天前
|
Java
在Java多线程编程中,实现Runnable接口通常优于继承Thread类
【10月更文挑战第20天】在Java多线程编程中,实现Runnable接口通常优于继承Thread类。原因包括:1) Java只支持单继承,实现接口不受此限制;2) Runnable接口便于代码复用和线程池管理;3) 分离任务与线程,提高灵活性。因此,实现Runnable接口是更佳选择。
29 2
|
20天前
|
Java
Java中多线程编程的基本概念和创建线程的两种主要方式:继承Thread类和实现Runnable接口
【10月更文挑战第20天】《JAVA多线程深度解析:线程的创建之路》介绍了Java中多线程编程的基本概念和创建线程的两种主要方式:继承Thread类和实现Runnable接口。文章详细讲解了每种方式的实现方法、优缺点及适用场景,帮助读者更好地理解和掌握多线程编程技术,为复杂任务的高效处理奠定基础。
27 2
|
20天前
|
Java 开发者
Java多线程初学者指南:介绍通过继承Thread类与实现Runnable接口两种方式创建线程的方法及其优缺点
【10月更文挑战第20天】Java多线程初学者指南:介绍通过继承Thread类与实现Runnable接口两种方式创建线程的方法及其优缺点,重点解析为何实现Runnable接口更具灵活性、资源共享及易于管理的优势。
27 1
|
2月前
|
Java 编译器
封装,继承,多态【Java面向对象知识回顾①】
本文回顾了Java面向对象编程的三大特性:封装、继承和多态。封装通过将数据和方法结合在类中并隐藏实现细节来保护对象状态,继承允许新类扩展现有类的功能,而多态则允许对象在不同情况下表现出不同的行为,这些特性共同提高了代码的复用性、扩展性和灵活性。
封装,继承,多态【Java面向对象知识回顾①】
|
1月前
|
Java 测试技术 编译器
Java零基础-继承详解!
【10月更文挑战第4天】Java零基础教学篇,手把手实践教学!
33 2
|
1月前
|
Java 编译器
在Java中,关于final、static关键字与方法的重写和继承【易错点】
在Java中,关于final、static关键字与方法的重写和继承【易错点】
21 5
|
1月前
|
Java
java继承和多态详解
java继承和多态详解
41 5
|
1月前
|
Java 编译器
【一步一步了解Java系列】:子类继承以及代码块的初始化
【一步一步了解Java系列】:子类继承以及代码块的初始化
22 3