继承与多态
继承与多态
继承问题的引出
详情
类继承定义
类继承
面向对象的可重用性不仅仅局限于类或方法的包装,还存在于已有类结构的扩充上,在 Java 中可以通过 extends 关键字实现类继承的结构定义,此关键字的使用语法如下:
- class 子类 extends 父类{}
详情
public class Book {
private String title;
private String author;
private double price;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}
class MathBook extends Book {
private int type;
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
}
class Test {
public static void main(String[] args) {
MathBook mathBook = new MathBook();
mathBook.setTitle("线性代数");
mathBook.setAuthor("小陈老师");
mathBook.setPrice(58.6);
mathBook.setType(2);
System.out.println("图书名:" + mathBook.getTitle() + ";图书作者:" + mathBook.getAuthor() + ";图书价格:" + mathBook.getPrice() + ";图书类型:" + mathBook.getType());
}
}
图书名:线性代数;图书作者:小陈老师;图书价格:58.6;图书类型:2
子类对象实例化流程
子类对象实例化流程
class Animal{
public Animal(){
System.out.println("【动物父类】实例化Animal类对象");
}
}
class Dog extends Animal{
public Dog(){
System.out.println("【狗子类】实例化Dog类对象");
}
}
class AmTest{
public static void main(String[] args) {
new Dog();
}
}
【动物父类】实例化Animal类对象
【狗子类】实例化Dog类对象
super()观察
class Animal {
public Animal() {
System.out.println("【动物父类】实例化Animal类对象");
}
public Animal(String name, String boss, int age) {
System.out.println("【动物父类】实例化Animal三参构造方法");
}
}
class Dog extends Animal {
public Dog() {
System.out.println("【狗子类】实例化Dog类对象");
}
public Dog(String name, String boss, int age) {
super(name, boss, age);
System.out.println("【狗子类】实例化Dog三参构造方法");
}
}
class AmTest1 {
public static void main(String[] args) {
new Dog("毛毛", "王大祥", 8);
}
}
【动物父类】实例化Animal三参构造方法
【狗子类】实例化Dog三参构造方法
继承限制
一个子类只能够继承一个父类,存在有单继承局限。
在 Java 中为了保证代码的唯一性,不允许一个子类同时继承多个父类,即:一个子类只允许继承一个父类,子类对象实例化必须对其父类进行初始化操作。
当一个子类继承父类之后,实际上会同时继承父类之中的全部定义结构,但是对于所有的非私有操作属于显式继承,而所有的私有操作属于隐式继承(不能够直接进行访问) private getTitle
范例:错误的类继承
错误的类继承
class Book{}
class Toilet{}
class MathBook extends Book,Toilet{}
class Book{}
class MathBook extends Book{}
class LinearAlgebra extends MathBook{}
Book
private String title;
public String getTitle() {
return title;
}
MathBook extends Book
public void getInfo() {
System.out.println("动物名字" + this.getTitle());
}
覆写功能简介
- 在程序开发中通过类继承的结构可以有效的实现某一个类中的代码结构的复用,但是在子类的开发过程中除了需要依据自身的需要进行功能实现之外,还有可能需要对父类定义的某些操作进行功能扩充,这时就可以通过重用已有的结构名称的方式来进行处理,这样的功能就称为覆写
- 方法的覆写
- 属性的覆写
方法覆写
方法覆写
public class Book {
public String getInfo() {
return "【Book】这是普通图书";
}
}
class MathBook extends Book {
public String getInfo() {
return "【MathBook】这是数学知识的书";
}
}
class Test {
public static void main(String[] args) {
MathBook mathBook = new MathBook();
System.out.println(mathBook.getInfo());
}
}
【MathBook】这是数学知识的书
public class Book {
private String title;
private String author;
private double price;
public Book(String title, String author, double price) {
this.title = title;
this.author = author;
this.price = price;
}
public String getInfo() {
return "图书名称:" + this.title + "、图书作者:" + this.author + "、图书价格:" + this.price;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}
class MathBook extends Book {
private String type;
public MathBook(String title, String author, double price, String type) {
super(title, author, price);
this.type = type;
}
@Override
public String getInfo() {
return super.getInfo() + "、学科:" + this.type;
}
}
class Test {
public static void main(String[] args) {
MathBook mathBook = new MathBook("线性代数", "小陈老师", 59.3, "大学数学");
System.out.println(mathBook.getInfo());
}
}
图书名称:线性代数、图书作者:小陈老师、图书价格:59.3、学科:大学数学
方法覆写限制
- 被子类所覆写的方法不能拥有比父类更严格的访问控制权限,对于访问控制权限现在已经接触过三种:“private<default(不写)<public”
- 如果现在父类中的方法使用的是 default 权限,则在子类覆写的时候方法可以使用 default 或 public 两类权限,如果此时父类中的方法使用的是 public 权限,那么在子类中方法只能够使用 public 权限进行覆写。
详情
属性覆盖
详情
final 关键字
- final 在程序之中描述为终接器的概念,在 java 里面使用 final 关键字可以实现如下的功能定义不能够被继承的类、定义不能够被覆写的方法、常量(全局常量)。
- 使用 final 定义的类不允许有子类
- 使用 final 定义的方法不允许被子类覆写
- 使用 final 定义的变量就属于一个常量
public final class Book {
}
class MathBook extends Book{
}
Annotation 简介
软件开发的三个发展阶段
如果要想清楚 Annotation 的产生意义,则必须了解一下程序开发结构的历史,从历史上来讲程序的开发一共分为了三个过程(以程序开发所需要的服务器信息为例):
- 阶段一:在程序定义的时候将所有可能使用到的资源全部定义在程序代码之中;
- 如果此时服务器的相关的地址发生了改变,那么对于程序而言就需要进行源代码的修改了,维护需要由开发人员来完成,这样的做法明显是不方便的;
- 阶段二:引入配置文件,在配置文件之中定义全部要使用的服务器资源
- 在配置项不多的情况下,此类配置非常好用,并且十分的简单,但是如果这个时候所有的项目都是采用这种结构开发,那么就可能出现一种可怕的场景:配置文件过多,维护困难;
- 阶段三:将配置信息重新写回到程序里面,利用一些特殊的标记与程序代码进行分离,这就是注解的作用,也就是说 Annotation 提出的基本依据。
- 如果全部都使用注解开发,难度太高了,配置文件有好处也有缺点,所以现在人们的开发基本上是围绕着配置文件 +注解的形式完成的。
Annotation
Annotation 是在 JDK 1.5 之后推出的重要开发技术,利用 Annotation 注解可以实现代码的简化开发,也是现代 Java 框架开发技术的重要组成部分,为方便读者理解 Annotation 的使用,本次先为读者讲解三个基础 Annotation:@Override、@Deprecated、@SuppressWarnings.
准确覆写
准确覆写
public class Book {
public String getInfo() {
return "【Book】这是图书信息";
}
}
class MathBook extends Book {
@Override
public String getInfo() {
return super.getInfo() + "【MathBook】这是数学图书信息";
}
}
class Test {
public static void main(String[] args) {
System.out.println(new MathBook().getInfo());
}
}
【Book】这是图书信息【MathBook】这是数学图书信息
过期声明
- 项目周期迭代与方法过期 任何的软件项目开发都不是一次性完成的,每一个项目的成功上线都可能会经历大量的迭代的开发过程,每一次版本迭代都有可能完成新的功能,同时也有可能发现一些程序类所出现的缺陷,这样就需要使用一些新的方法来代替已有的旧方法,但是考虑到很多的历史版本或者与这个项目衍生的其他系统里面原始的方法可以正常的提供服务,,所以这种情况下就建议保留这个旧方法,同时给出一个新的方法,并且告诉后来的使用者这个旧方法不建议再去使用了,这种机制就属于过期声明
public class Book {
@Deprecated
public String getInfo() {
return "【Book】这是图书信息";
}
}
class Test11 {
public static void main(String[] args) {
Book book = new Book();
System.out.println(book.getInfo());
}
}
压制警告
deprecation
unchecked
fallthrough
path
serial
finally
public class Book {
@Deprecated
public String getInfo() {
return "【Book】这是图书信息";
}
}
class Test11 {
@SuppressWarnings(value = {"deprecation"})
public static void main(String[] args) {
Book book = new Book();
System.out.println(book.getInfo());
}
}
多态性简介
方法的多态性(同样的方法有不同的实现)
方法的重载:同一个方法名称可以根据其定义方法的参数类型与个数不同实现不同方法体的调用
方法的覆写:同一个方法会根据覆写该方法子类的不同而实现不同的功能
对象多态性(父子实例之间的转换)
- 对象向上转型:父类 父类实例=子类实例、自动完成转换
- 对象向下转型:子类 子类实例=(子类)父类实例、强制完成转换。
对象向上转型
public class Book {
public String getInfo() {
return "【Book】这是图书信息";
}
}
class MathBook extends Book {
@Override
public String getInfo() {
return super.getInfo() + "【MathBook】这是数学图书信息";
}
}
class Test {
public static void main(String[] args) {
Book book = new MathBook(); //向上转型
System.out.println(book.getInfo());
}
}
案例
public class Book {
public String getInfo() {
return "【Book】这是图书信息";
}
}
class MathBook extends Book {
@Override
public String getInfo() {
return "【MathBook】这是数学图书信息";
}
}
class ProgramBook extends Book {
@Override
public String getInfo() {
return "【ProgramBook】这是计算机图书信息";
}
}
class Test {
public static void main(String[] args) {
fun(new Book());
fun(new MathBook());
fun(new ProgramBook());
}
public static void fun(Book book) {
System.out.println(book.getInfo());
}
}
【Book】这是图书信息
【MathBook】这是数学图书信息
【ProgramBook】这是计算机图书信息
对象向下转型
对象向下转型的意义 对象向下转型的核心意义是需要调用子类的特殊功能,例如:人是一个基础的父类,在人这个类的基础上派生出教师类以及超人类,教师类和超人类彼此都有特定的扩充方法功能(要比普通的人这个类所具备的功能更加丰富),教师和超人都属于人都具备人的基本行为,但是如果要想调用一些特殊的处理,那么就必须通过特定的子类来完成
案例
public class Book {
public void read() {
System.out.println("【Book】开始阅读");
System.out.println(this.getInfo());
}
public String getInfo() {
return "【Book】这是图书信息";
}
}
class MathBook extends Book {
@Override
public String getInfo() {
return "【MathBook】这是数学图书信息";
}
public void calc() {
System.out.println("【MathBook】根据数学公式计算");
System.out.println(this.getInfo());
}
}
class Test {
public static void main(String[] args) {
Book book = getBookInstance();
book.read();
System.out.println("---------------------------");
MathBook mathBook = (MathBook) book;
mathBook.calc();
}
public static Book getBookInstance() {
return new MathBook();
}
}
【Book】开始阅读
【MathBook】这是数学图书信息
---------------------------
【MathBook】根据数学公式计算
【MathBook】这是数学图书信息
instanceof 关键字
instanceof 为了保证对象向下转型可以安全的实现处理,最佳的做法是在转型之前判断某一个对象实例是否属于某个类,为了解决这个问题,在 Java 中提供了一个 instanceof 关键字,此关键字使用的基本语法如下:
- 实例化对象 instanceof 类 =>=> 返回 boolean 型判断结果
案例
public class Book {
}
class MathBook extends Book {
}
class Test {
public static void main(String[] args) {
Book bookA = new Book();
System.out.println("【未发生向上转型】" + (bookA instanceof Book));
System.out.println("【未发生向上转型】" + (bookA instanceof MathBook));
System.out.println("--------------------------------------------");
Book bookB = new MathBook();
System.out.println("【发生向上转型】" + (bookB instanceof Book));
System.out.println("【发生向上转型】" + (bookB instanceof MathBook));
}
}
【未发生向上转型】true
【未发生向上转型】false
--------------------------------------------
【发生向上转型】true
【发生向上转型】true
Object 类简介
Object 类 在 Java 语言设计过程之中,为了方便操作类型的统一,也为方便为每一个类定义一些公共操作,所以专门设计一个公共的 Obiect 父类(此类是唯一一个没有父类的类,但确是所有类的父类),所有利用 class 关键字定义的类全部都默认继承自 Object 类,即如下两种类的定义效果是相同的。
- class Book{}
- class Book extends Object {}
案例
/**
* 通过Object接收String对象实例
*
* @author wangdx
*/
public class Test {
public static void main(String[] args) {
Object obj = "一项集团:www.yix.coom";
if(obj instanceof String){
String msg = (String) obj;
System.out.println(msg.toUpperCase());
}
}
}
一项集团:WWW.YIX.COOM
/**
* 数组和Object转换
*/
class Test1 {
public static void main(String[] args) {
print(new int[]{5, 4, 55, 14, 2});
}
public static void print(Object param) {
if (param instanceof int[]) {
int[] array = (int[]) param;
for (int temp : array) {
System.out.print(temp + "、");
}
System.out.println();
}
}
}
获取对象信息
案例
public class Book {
private String title;
private String author;
private double price;
public Book(String title, String author, double price) {
this.title = title;
this.author = author;
this.price = price;
}
@Override
public String toString() {
return super.toString() + "【Book】图书标题:" + this.title + "、图书作者:" + this.author + "、图书价格:" + this.price;
}
}
class Test {
public static void main(String[] args) {
System.out.println(new Book("Java就业变成", "理想化", 89.9)); //默认调用toString()
}
}
extend.w09.Book@7bb11784【Book】图书标题:Java就业变成、图书作者:理想化、图书价格:89.9
``
### 对象比较
```java
public class Book {
private String title;
private String author;
private double price;
public Book(String title, String author, double price) {
this.title = title;
this.author = author;
this.price = price;
}
@Override
public String toString() {
return super.toString() + "【Book】图书标题:" + this.title + "、图书作者:" + this.author + "、图书价格:" + this.price;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof Book)) {
return false;
}
Book book = (Book) obj;
return this.title.equals(book.title) && this.author.equals(book.author) && this.price == book.price;
}
}
class Test1 {
public static void main(String[] args) {
Book bookA = new Book("Java就业变成", "理想化", 89.9);
Book bookB = new Book("Java就业变成", "理想化", 89.9);
if(bookB.equals(bookA)){
System.out.println("两个对象一祥");
}else {
System.out.println("两个对象不一样");
}
}
}
两个对象一祥