Java从入门到精通笔记篇(六)

继承 多态 抽象类与接口

继承机制下,用户可以复用一些定义好的类,减少重复代码的编写。多态机制下,用户可以动态调整对象的调用,降低对象之间的依存关系。

类的继承

一个类继承另一个类需要使用关键字extends。Java只支持单继承,即一个类只能有一个父类。

eg:class Childextends Parent{}

注意:子类在继承父类之后,创建子类对象的同时也会调用父类的构造方法。

eg:父类Parent和子类Child都各自有一个无参的构造方法,在main()方法中创建子类对象时,Java虚拟机会先执行父类的构造方法,然后执行子类的构造方法。

运行结果:

调用父类构造方法

调用子类构造方法

子类继承父类之后可以调用父类创建好的属性和方法。

Java虽然不允许同时继承两个父类,但不代表没有多继承的关系,可以通过类似“祖父>父>儿子>孙子”的方式实现多代继承。

Object类

Object类是比较特殊的类,它是所有类的父类,是Java类层中的最高层类。用户创建一个类时,除非已经指定它从其他类继承,否则它就是从java.lang.Object类继承而来的。Java中的每个类都源自java.lang.Object类,如String类、Integer类等都是继承自Object类。除此之外,自定义的类也都继承自Object类。由于所有类都是Object类的子类,因此在定义类时可省略extends Object。

在Object类中,主要包括clone()、finalize()、equals()、toString()等方法,其中常用的两个方法为equals()和toString()。由于所有的类都是Object类的子类,因此任何类都可以重写Object类中的方法。

注意Object类中的getClass()、notify()、notifyAll()、wait()等方法不能被重写,因为这些方法被定义为final类型。

getClass()方法

返回对象执行时的Class实例,然后使用此实例调用getName()方法可以取得类的名称。

eg:getClass().getname()

toString()方法

功能是将一个对象返回为字符串形式,它会返回一个String实例。在实际的应用中通常重写toString()方法,为对象提供一个特定的输出模式。

equals()方法

两种比较对象的方式,分别为“==”运算符与equals()方法。二者的区别在于:“==”比较的是两个对象引用内存地址是否相等,而equals()方法比较的是两个对象的实际内容。

对象类型的转换

向上转型

把子类类型的对象直接赋值给父类类型的对象,从而实现按照父类描述子类的效果。

向上转型是安全的,因为向上转型是将一个较具体的类的对象转换为一个较抽象的类的对象。例如,可以说平行四边形是四边形,但不能说四边形是平行四边形。

在运用向上转型的过程中,父类的对象无法调用子类独有的属性或者方法。

向下转型

向下转型可以被理解为将父类类型的对象转换为子类类型的对象。但是,运用向下转型,如果把一个较抽象的类的对象转换为一个较具体的类的对象,这样的转型通常会出现错误。

例如,可以说某只鸽子是一只鸟,却不能说某只鸟是一只鸽子。因为鸽子是具体的,鸟是抽象的。一只鸟除了可能是鸽子,还有可能是老鹰、麻雀等。因此,向下转型是不安全的。

如果想要告诉编译器“某只鸟就是一只鸽子”,应该如何修正?答案就是强制类型转换。

子类类型 子类对象 = (子类类型) 父类对象

注意

(1)两个没有继承关系的对象不可以进行向上转型或者向下转型。

(2)父类对象可以强制转换为子类对象,但有一个前提:这个父类对象要先引用这个子类对象。

instanceof关键字及其新特性

在执行向下转型之前需要判断父类对象是否为子类对象的实例。这个判断通常使用instanceof关键字来完成,它可以判断是否一个类实现了某个接口,也可以用它来判断一个实例对象是否属于一个类。如果两者没有继承关系,则不能使用这个关键词进行比较。

instanceof是Java语言的关键字,Java语言中的关键字都为小写。

instanceof的语法格式如下,返回值为布尔值:

myobject instanceof instanceof

方法的重载

为了让方法名相同而形参不同的构造方法同时存在,必须用到方法重载。方法的重载就是在同一个类中允许存在一个以上的同名方法,只要这些方法的参数个数或类型不同即可。

在谈到参数个数可以确定两个方法是否具有重载关系时,会想到定义不定长参数方法。不定长方法的语法如下:

返回值 方法名(参数数据类型...参数名称)

编译器会将“int…a”这种形式看作是“int[] a”。

final关键字

final变量

凡是被final关键字修饰过的内容都是不可改变的。

通常,由final关键字定义的变量为常量,且必须在声明时对其进行赋值操作。

final关键字可以修饰数组。一个对象引用一旦被修饰为final关键字后,它就只能恒定指向一个对象,无法将其改变以指向另一个对象。一个既是static又是final的字段只占据一段不能改变的存储空间。

final方法

final类型,可以防止子类修改父类的定义与实现方式。如果一个父类的某个方法被设置为private,子类将无法访问该方法,自然无需final方法。

如果将某个类设置为final类,则该类中的所有方法都被隐式地设置为final方法,但是final类中的成员变量可以被定义为final或非final形式。

record类是一种final类,即不可变类。

多态

如果定义一个图形类,让它处理所有继承该类的对象,根据“向上转型”原则可以使每个继承图形类的对象作为draw()方法的参数,然后在draw()方法中做一些限定就可以根据不同图形类对象绘制相应的图形。

抽象类

使用abstract关键字定义的类被称为抽象类,而使用这个关键字定义的方法被称为抽象方法。只要类中有一个抽象方法,此类就被标记为抽象类。

这些类是从图形类中导出的,同时某些类还需要draw()方法,而Java中规定类不能同时继承多个父类。为了应对这种问题,接口的概念便出现了。

接口

接口是抽象类的延伸,接口中的所有方法都没有方法体。

接口使用interface关键字进行定义

一个类继承一个父类的同时再实现一个接口,可以写成如下形式:

在接口中定义的任何字段都自动是static和final的。

类虽然不可以同时继承多个类,但可以同时实现多个接口。

当类同时实现多个接口时,要将所有需要实现的接口放在implements关键字后,并用英文格式下的逗号“,”隔开。类同时实现多个接口语法如下:

如果是接口继承接口,那么应该使用extends关键字,而不是implements关键字。接口继承接口的语法如下:

需要注意的是,如果类实现了子接口,那么在类中就需要同时重写父接口和子接口中所有的抽象方法。示例代码如下:

接口可以同时继承多个父接口

接口的默认方法

接口新增了两个默认方法,即default方法和static方法

default方法既可以被子接口继承,也可以被其实现类调用。default方法被继承时,可以被子接口重写方法。

static方法,指的是接口里的静态方法,即static修饰的有方法体的方法。它不会被继承或者实现,只能被自身调用。

接口实现类必须通过特殊语法指定该实现类要实现哪个接口的default方法。特殊语法的格式如下:

<接口>.super.<方法名>([参数])

定义Test类,并且实现DefalutMethods接口。在Test类中重写default方法,并且使用特殊语法调用DefalutMethods接口中的default方法。代码如下:

抽象类与接口的区别

 抽象类和接口都可以有子类,其中把接口的子类称作实现类。

 抽象类通常作为子类的“模板”,接口通常用来描述子类的“行为”。

 子类虽然只能继承一个抽象类,但可以同时实现任意多个接口。

 创建抽象类需要使用abstract关键字,创建接口需要使用interface关键字。

 声明抽象类中的抽象方法需要使用abstract关键字,声明接口中的抽象方法可以省略abstract关键字。

 在接口中可以使用default关键字定义有方法体的非抽象方法,但是在抽象类中不能用。

 在接口中不能有构造方法,但是在抽象类中可以有。

 在抽象类中可以有代码块、静态代码块和静态方法,但是在接口中不能有。

 抽象类中的成员属性可以定义为任意权限、任意类型、静态或非静态的变量,但是接口中的成员属性只能是静态常量。

 子接口可以同时继承多个父接口,但是子抽象类只能继承一个父抽象类。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值