继承
多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那个类即可。
通过 extends 关键字让类与类之间产生继承关系。
多个类可以称为子类,单独这个类称为父类或者超类或者基类。
简化代码:
抽取相同的属性和方法到Person
package com.sram.entity; public class Person { //属性 private String name; private int age; private String sex; //提供getter和setter方法 public void setName(String name) { this.name = name; } public String getName() { return name; } public void setAge(int age) { this.age = age; } public int getAge() { return age; } public void setSex(String sex) { this.sex = sex; } public String getSex() { return sex; } } |
现在将属性和方法进行抽取,那么咱们的Student类和Teacher类中就不需要再编写相同的那三个属性和六个方法。只需要继承Person类。
Student继承Person类:
public class Student extends Person{ private String code; //提供getter和setter方法 public void setCode(String code) { this.code = code; } public String getCode() { return code; } } |
Teacher继承Person类:
public class Teacher extends Person{ //属性 private int teachAge; //提供getter和setter方法 public void setTeachAge(int teachAge) { this.teachAge = teachAge; } public int getTeachAge() { return teachAge; } } |
上面的代码实现了两个类继承同一个类,继承的出现将不同类划分为不同的类型:
多个类可以称为子类,单独这个类称为父类或者超类或者基类。 |
子类:Student和Teacher类 父类:Person类 |
继承的限制
继承可以很好的解决代码的冗余(代码重复),但是在使用继承的时候必须遵循一下的绩点:
1、Java只支持单继承,不支持多继承。
一个类只能有一个父类,不可以有多个父类。 class SubDemo extends Demo{} //ok class SubDemo extends Demo1,Demo2...//error |
2、Java支持多重继承(继承体系)
class A{} class B extends A{} class C extends B{} |
3、不要仅为了获取其他类中某个功能而去继承。
访问限制
在使用继承的时候也应注意的是:子类是不能直接访问父类中的私有成员的,但是子类可以调用父类中的非私有方法,但是不能直接调用父类中的私有成员。
子类对象实例化过程
对象的实例化其实就是创建对象。
在继承的操作中,对于子类对象的实例化也是有要求的:“子类对象在实例化之前必须首先调用父类中的构造方法之后再调用子类自己的构造方法”。
案例:
public Person(){ System.out.println("Person无参构造方法"); } |
public Student(){ System.out.println("Student中无参构造方法"); } |
public static void main(String[] args) { Student student=new Student(); } |
Person无参构造方法 Student中无参构造方法 |
通过上面的代码发现确实是在创建子类对象的时候子类中的构造方法默认的调用了父类中的构造方法。
方法的覆盖(Override)
在之前学习了方法的重载:同一个类中出现了多个名称一样但是参数的类型或者个数不同。
子类中出现与父类一模一样的方法时,会出现覆盖操作,也称为重写或者复写。
案例:
public class Person { public void show(){ System.out.println("Person---->show()"); } } |
public class Student extends Person{ public void show(){ System.out.println("Student--->show()"); } } |
public static void main(String[] args) { Student student=new Student(); student.show(); } |
Person无参构造方法 Student中无参构造方法 Student--->show() |
覆盖注意事项
方法的重载与覆写的区别
- 覆盖时,子类方法权限一定要大于等于父类方法权限
- 当子类需要父类的功能,而功能主体子类有自己特有内容时,可以复写父类中的方法,这样,即延续了父类的功能,又定义了子类特有的内容。
No. | 区别点 | 重载 | 覆写 |
1 | 单词 | Overloading | Overriding |
2 | 定义 | 方法名称相同,参数的类型或个数不同 | 方法名称、参数的类型、返回值类型全部相同 |
3 | 对权限没有要求 | 被覆写的方法不能拥有更严格的权限 | |
4 | 范围 | 发生在一个类中 | 发生在继承类中 |
继承后子类和父类的关系
- 子类中所有的构造函数默认都会访问父类中空参数的构造函数
- 因为每一个构造函数的第一行都有一条默认的语句super();
- 子类会具备父类中的数据,所以要先明确父类是如何对这些数据初始化的。
- 当父类中只有带参数的构造函数时,子类的构造函数必须通过super语句明确指定要访问的构造函数。
多态性
面向对象有三大特征:封装,继承,多态,前面的两种是笔记哦啊传统的,在实际的应用主要是看程序的设计者思想的体现,但是多态性在Java中其实也是希望能够更加灵活的去操作的对象,操作对象其实就是操作堆栈内存。
多态性的概念
Java中面向对象的多态性一共就有如下的两点:
对象多态性
- 方法的重载和覆写
- 、对象的多态性 向上转型 向下转型
对象多态性其实就是在Java中一个对象可以以不同的形态出现在程序中。
对象的多态性主要分为以下两种类型:
1、向上转型:子类对象----->父类对象
对于向上转型,程序会自动完成,格式:
对象向上转型:父类 父类对象 = 子类实例 ; |
2、向下转型:父类对象------>子类对象
对于向下转型时,必须明确的指明要转型的子类类型,格式:
对象向下转型:子类 子类对象 = (子类)父类实例 ; |
多态的使用
程序中体现:
父类或者接口的引用指向或者接收自己的子类对象。
好处和作用:
多态的存在提高了程序的扩展性和后期可维护性
前提:
需要存在继承或者实现关系
要有覆盖操作
案例:
向上转型
public static void main(String[] args) { //创建子类的对象 Student student=new Student("张三",23, "男", "20180201"); System.out.println(student); //创建父类对象 Person person=student;//向上转型 person.eat();//调用的学生的方法 } |
姓名张三,年龄:23,性别:男,学号:20180201 我是学生,靠父母吃饭 |
通过上面的案例发现子类对象可以转换成父类对象,但是父类对象只能调用子类覆写的父类的方法,子类自己的方法父类对象无法调用。
向下转型
父类对象转换成子类对象
Person person=new Person("张三", 23, "男"); System.out.println(person); //转换成子类对象 Student student=(Student)person; |
Exception in thread "main" java.lang.ClassCastException: com.sram.entity.Person cannot be cast to com.sram.entity.Student at com.sram.test.MyTest.main(MyTest.java:17) |
上面编写的代码主要是将父类对象转换成子类对象,代码在编译的时候没有任何的问题,但是在执行的时候发现出现了上面的错误。之所以出现上面的问题是因为现在person对象根部不知道student对象是不是自己的子类对象,所以在转换的时候出现了类型转换异常,现在想要发生向下转型首先得发生向上转型。
//创建父类对象 Person person=new Person("张三", 23, "男"); System.out.println(person); //向上转型 person=new Student("张三",23, "男", "20180201"); //转换成子类对象 Student student=(Student)person;//发生强制转换 System.out.println(student); |
com.sram.entity.Person@15db9742 姓名张三,年龄:23,性别:男,学号:20180201 |
上面的代码才是发生向下转型的基本操作。在以后的操作中大家一定要注意对象关系的设定,不要随便去进行一个转换操作。