继承、抽象类、接口、多态、静态

继承

继承的好处
子类在继承父类的时候,会自动拥有父类的成员。

  1. 提高代码的复用性。
  2. 类与类之间产生了关系,是多态的前提。

成员变量重名:

  • 如果子类父类中出现不重名的成员变量,这时的访问是没有影响的。

  • 子父类中出现了同名的成员变量时,在子类中需要访问父类中非私有成员变量时,需要使用super 关键字,修饰父类成员变量,类似于之前学过的 this 。
    使用格式:super.父类成员变量名

成员方法重名——方法重写 :

  • 子类中出现与父类一模一样的方法时(返回值类型,方法名和参数列表都相同),会出现覆盖效果,也称为重写或者覆写。声明不变,重新实现。

  • Fu 类中的成员变量是非私有的,子类中可以直接访问。若Fu 类中的成员变量私有了,子类是不能直接访问的。

重写的应用:

  • 子类可以根据需要,定义特定于自己的行为。既沿袭了父类的功能名称,又根据子类的需要重新实现父类方法,从而进行扩展增强。

注意事项:

  1. 子类方法覆盖父类方法,必须要保证权限大于等于父类权限。
  2. 子类方法覆盖父类方法,返回值类型、函数名和参数列表都要一模一样。
  3. 私有方法不能被重写(父类私有成员子类是不能继承的)

继承后的特点——构造方法:

  • 构造方法的名字是与类名一致的。所以子类是无法继承父类构造方法的。
  • 构造方法的作用是初始化成员变量的。所以子类的初始化过程中,必须先执行父类的初始化动作。子类的构造方法中默认有一个super() ,表示调用父类的构造方法,父类成员变量初始化后,才可以给子类使用。

super和this:

super :代表父类的存储空间标识(可以理解为父亲的引用)。
this :代表当前对象的引用(谁调用就代表谁)。

  • 子类的每个构造方法中均有默认的super(),调用父类的空参构造。手动调用父类构造会覆盖默认的super()。
  • super() 和 this() 都必须是在构造方法的第一行,所以不能同时出现。

继承的特点:
Java只支持单继承,不支持多继承。
所有的类都直接或者间接继承了Object类,Object类是所有类的父类。

父类空间优先于子类对象产生

在每次创建子类对象时,先初始化父类空间,再创建其子类对象本身。目的在于子类对象中包含了其对应的父类空间,便可以包含其父类的成员,如果父类成员非private修饰,则子类可以随意使用父类成员。代码体现在子类的构造方法调用时,一定先调用父类的构造方法。

抽象类

定义:

  • 抽象方法 : 没有方法体的方法。
  • 抽象类:包含抽象方法的类。

抽象方法: 使用abstract 关键字修饰方法,该方法就成了抽象方法,抽象方法只包含一个方法名,而没有方法体。
定义格式:

修饰符 abstract 返回值类型 方法名 (参数列表);

抽象类: 如果一个类包含抽象方法,那么该类必须是抽象类。
定义格式:public abstract class 类名字 { }

抽象类的使用:

  • 继承抽象类的子类必须重写父类所有的抽象方法。否则,该子类也必须声明为抽象类。最终,必须有子类实现该父类的抽象方法,否则,从最初的父类到最终的子类都不能创建对象,失去意义。

注意事项:

  1. 抽象类不能创建对象,如果创建,编译无法通过而报错。只能创建其非抽象子类的对象。
    理解:假设创建了抽象类的对象,调用抽象的方法,而抽象方法没有具体的方法体,没有意义。
  2. 抽象类中,可以有构造方法,是供子类创建对象时,初始化父类成员使用的。
    理解:子类的构造方法中,有默认的super(),需要访问父类构造方法。
  3. 抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
    理解:未包含抽象方法的抽象类,目的就是不想让调用者创建该类对象,通常用于某些特殊的类结构设计。
  4. 抽象类的子类,必须重写抽象父类中所有的抽象方法,否则,编译无法通过而报错。除非该子类也是抽象类。
    理解:假设不重写所有抽象方法,则类中可能包含抽象方法。那么创建对象后,调用抽象的方法,没有意义。

接口

引用数据类型:数组,类,接口。

定义格式: public interface 接口名称 { // 抽象方法 // 默认方法 // 静态方法 }

接口的使用,它不能创建对象,但是可以被实现(implements ,类似于被继承)。一个实现接口的类(可以看做是接口的子类),需要实现接口中所有的抽象方法,创建该类对象,就可以调用方法了,否则它必须是一个抽象类。

抽象方法: 使用abstract 关键字修饰,可以省略,没有方法体。该方法供子类实现使用。必须全部实现

默认方法: 使用 default 修饰,不可省略,供子类调用或者子类重写。可以继承,可以重写,二选一,但是只能通过实现类的对象来调用。

静态方法: 使用 static 修饰,供接口直接调用。静态与.class 文件相关,只能使用接口名调用,不可以通过实现类的类名或者实现类的对象调用

基本的实现:
类与接口的关系为实现关系,即类实现接口,该类可以称为接口的实现类,也可以称为接口的子类。实现的动作类似继承,格式相仿,只是关键字不同,实现使用 implements关键字。

非抽象子类实现接口:

  1. 必须重写接口中所有抽象方法。
  2. 继承了接口的默认方法,即可以直接调用,也可以重写。
  • 抽象方法: 接口中,有多个抽象方法时,实现类必须重写所有抽象方法。如果抽象方法有重名的,只需要重写一次。
  • 默认方法:接口中,有多个默认方法时,实现类都可继承使用。如果默认方法有重名的,必须重写一次。
  • 静态方法:接口中,存在同名的静态方法并不会冲突,原因是只能通过各自接口名访问静态方法。

优先级的问题:
当一个类,既继承一个父类,又实现若干个接口时,父类中的成员方法与接口中的默认方法重名,子类就近选择执行父类的成员方法。

接口的继承使用 extends 关键字,子接口继承父接口的方法。如果父接口中的默认方法有重名的,那么子接口需要重写一次。

其他成员特点:

  • 接口中无法定义成员变量,但是可以定义常量,其值不可以改变,默认使用public static final修饰。
  • 接口中,没有构造方法,不能创建对象。
  • 接口中,没有静态代码块。

接口和抽象类的区别:

相同点:

 都位于继承的顶端,用于被其他类实现或继承;

 都不能直接实例化对象;

 都包含抽象方法,其子类都必须覆写这些抽象方法;

区别:

抽象类为部分方法提供实现,避免子类重复实现这些方法,提高代码重用性;接口只能包含抽象方法;

一个类只能继承一个直接父类(可能是抽象类),却可以实现多个接口;(接口弥补了Java的单继承)

抽象类为继承体系中的共性内容,接口为继承体系中的扩展功能
  • 成员区别
    • 抽象类
      变量,常量;有构造方法;有抽象方法,也有非抽象方法
    • 接口
      常量;抽象方法
  • 关系区别
    • 类与类
      继承,单继承
    • 类与接口
      实现,可以单实现,也可以多实现
    • 接口与接口
      继承,单继承,多继承
  • 设计理念区别
    • 抽象类
      对类抽象,包括属性、行为
    • 接口
      对行为抽象,主要是行为

多态

定义

  • 多态: 是指同一行为,具有多个不同表现形式。
  1. 继承或者实现【二选一】
  2. 方法的重写【意义体现:不重写,无意义】
  3. 父类引用指向子类对象【格式体现】

多态体现的格式:父类类型 变量名 = new 子类对象; 变量名.方法名();

当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,执行的是子类重写后方法。

多态的好处:
实际开发的过程中,父类类型作为方法形式参数,传递子类对象给方法,进行方法的调用,更能体现出多态的扩展性与便利。可以使程序编写的更简单,并有良好的扩展。

引用类型转换:
多态的转型分为向上转型与向下转型两种:
向上转型

  • 向上转型:多态本身是子类类型向父类类型向上转换的过程,这个过程是默认的。
    当父类引用指向一个子类对象时,便是向上转型。
    使用格式:父类类型 变量名 = new 子类类型(); 如:Animal a = new Cat();

向下转型

  • 向下转型:父类类型向子类类型向下转换的过程,这个过程是强制的。
    一个已经向上转型的子类对象,将父类引用转为子类引用,可以使用强制类型转换的格式,便是向下转型。
    使用格式:子类类型 变量名 = (子类类型) 父类变量名; 如:Cat c =(Cat) a;
    想要调用子类特有的方法,必须做向下转型。

类型转换异常!为了避免ClassCastException的发生,Java提供了 instanceof 关键字,给引用变量做类型的校验,格式如下:

变量名 instanceof 数据类型 
如果变量属于该数据类型,返回true。
如果变量不属于该数据类型,返回false。

final关键字

final: 不可改变。可以用于修饰类、方法和变量。

  • 类:被修饰的类,不能被继承。
  • 方法:被修饰的方法,不能被重写。
  • 变量:被修饰的变量,不能被重新赋值。

修饰类格式如下: final class 类名 { }
修饰方法格式如下:修饰符 final 返回值类型 方法名(参数列表){ //方法体 }

  • 局部变量——引用类型
    引用类型的局部变量,被final修饰后,只能指向一个对象,地址不能再更改。但是不影响对象内部的成员变量值的修改
  • 局部变量——基本类型
    基本类型的局部变量,被final修饰后,只能赋值一次,不能再更改。
  • 成员变量
    成员变量涉及到初始化的问题,初始化方式有两种,只能二选一。
    显示初始化;
    构造方法初始化。

static关键字

概述:
static是静态修饰符,一般修饰成员。被static修饰的成员属于类,不属于单个这个类的某个对象。static修饰的成员被多个对象共享。static修饰的成员属于类,但是会影响每一个对象。被static修饰的成员又叫类成员,不叫对象的成员。

静态方法调用的注意事项:

  • 静态方法可以直接访问类变量和静态方法。
  • 静态方法不能直接访问普通成员变量或成员方法。反之,成员方法可以直接访问类变量或静态方法。
  • 静态方法中,不能使用this关键字。

静态方法只能访问静态成员。

static 修饰的内容:

  • 是随着类的加载而加载的,且只加载一次。
  • 存储于一块固定的内存区域(静态区),所以,可以直接被类名调用。
  • 它优先于对象存在,所以,可以被所有对象共享。

静态代码块:定义在成员位置,使用static修饰的代码块{ }。

  • 位置:类中方法外。

  • 执行:随着类的加载而执行且执行一次,优先构造方法的执行。

    内部类

    • 内部类可以直接访问外部类的成员,包括私有成员。
  • 外部类要访问内部类的成员,必须要建立内部类的对象。

创建内部类对象格式:

外部类名.内部类名 对象名 = new 外部类型().new 内部类型();

匿名内部类
是内部类的简化写法。它的本质是一个带具体实现的 父类或者父接口的 匿名的 子类对象。
前提:存在一个类或者接口,这里的类可以是具体类也可以是抽象类。

类名作为方法参数和返回值

  • 类名作为方法的形参
    方法的形参是类名,其实需要的是该类的对象
    实际传递的是该对象的【地址值】
  • 类名作为方法的返回值
    方法的返回值是类名,其实返回的是该类的对象
    实际传递的,也是该对象的【地址值】

抽象类作为形参和返回值

  • 方法的形参是抽象类名,其实需要的是该抽象类的子类对象
  • 方法的返回值是抽象类名,其实返回的是该抽象类的子类对象

接口作为形参和返回值

  • 方法的形参是接口名,其实需要的是该接口的实现类对象
  • 方法的返回值是接口名,其实返回的是该接口的实现类对象

toString

  • public String toString():返回该对象的字符串表示。

toString方法返回该对象的字符串表示,其实该字符串内容就是对象的类型+@+内存地址值。

由于toString方法返回的结果是内存地址,而在开发中,经常需要按照对象的属性得到相应的字符串表现形式,因此也需要重写它。

equals

  • public boolean equals(Object obj):指示其他某个对象是否与此对象“相等”。

调用成员方法equals并指定参数为另一个对象,则可以判断这两个对象是否是相同的。这里的“相同”有默认和自定义两种方式。

默认地址比较

如果没有覆盖重写equals方法,那么Object类中默认进行==运算符的对象地址比较,只要不是同一个对象,结果必然为false。

对象内容比较

如果希望进行对象的内容比较,即所有或指定的部分成员变量相同就判定两个对象相同,则可以覆盖重写equals方法。

Date类

java.util.Date类 表示特定的瞬间,精确到毫秒。

  • public Date():分配Date对象并初始化此对象,以表示分配它的时间(精确到毫秒)。
  • public Date(long date):分配Date对象并初始化此对象,以表示自从标准基准时间(称为“历元(epoch)”,即1970年1月1日00:00:00 GMT)以来的指定毫秒数。
  • public long getTime() 把日期对象转换成对应的时间毫秒值。

使用无参构造,可以自动设置当前系统时间的毫秒时刻;指定long类型的构造参数,可以自定义毫秒时刻。

DateFormat类

java.text.DateFormat 是日期/时间格式化子类的抽象类,我们通过这个类可以帮我们完成日期和文本之间的转换,也就是可以在Date对象与String对象之间进行来回转换。

  • 格式化:按照指定的格式,从Date对象转换为String对象。
  • 解析:按照指定的格式,从String对象转换为Date对象。

构造方法

由于DateFormat为抽象类,不能直接使用,所以需要常用的子类java.text.SimpleDateFormat。这个类需要一个模式(格式)来指定格式化或解析的标准。构造方法为:

  • public SimpleDateFormat(String pattern):用给定的模式和默认语言环境的日期格式符号构造SimpleDateFormat。

参数pattern是一个字符串,代表日期时间的自定义格式。

DateFormat类的常用方法有:

  • public String format(Date date):将Date对象格式化为字符串。
  • public Date parse(String source):将字符串解析为Date对象。

Calendar类

java.util.Calendar是日历类,在Date后出现,替换掉了许多Date的方法。该类将所有可能用到的时间信息封装为静态成员变量,方便获取。日历类就是方便获取各个时间属性的。

获取方式

Calendar为抽象类,由于语言敏感性,Calendar类在创建对象时并非直接创建,而是通过静态方法创建,返回子类对象,如下:

Calendar静态方法

  • public static Calendar getInstance():使用默认时区和语言环境获得一个日历
    常用方法有:

  • public abstract void add(int field, int amount):根据日历的规则,为给定的日历字段添加或减去指定的时间量。

  • public void set(int field, int value):将给定的日历字段设置为给定值。

  • public int get(int field):返回给定日历字段的值。

  • public Date getTime():返回一个表示此Calendar时间值(从历元到现在的毫秒偏移量)的Date对象。

System类

java.lang.System类中提供了大量的静态方法,可以获取与系统相关的信息或系统级操作,在System类的API文档中,常用的方法有:

  • public static long currentTimeMillis():返回以毫秒为单位的当前时间。
  • public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length):将数组中指定的数据拷贝到另一个数组中。

currentTimeMillis方法
实际上,currentTimeMillis方法就是 获取当前系统时间与1970年01月01日00:00点之间的毫秒差值

arraycopy方法

  • public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length):将数组中指定的数据拷贝到另一个数组中。

数组的拷贝动作是系统级的,性能很高。System.arraycopy方法具有5个参数,含义分别为:
在这里插入图片描述

箱与拆箱

基本类型与对应的包装类对象之间,来回转换的过程称为”装箱“与”拆箱“:

  • 装箱:从基本类型转换为对应的包装类对象。
  • 拆箱:从包装类对象转换为对应的基本类型。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值