简单实例
父类Pet中有属性 name 和 age 和方法 eat 和sleep
子类Cat使用extend关键字继承了父类Pet,中间什么都没写
这就是继承的优点
思考一下:为什么会有继承?
当多个类中存在相同属性和行为时,为了提高代码复用性,将这些相同的内容抽取到一个单独的类中,这些多个类无需再定义这些属性和行为,只要去继承那一个单独的类即可。此处的多个类称为子类(派生类),单独的这个类称为父类(基类或超类)。
继承就是子类继承父类‘所有’的特征和行为,使得子类对象(实例)具有父类的成员变量和方法,还可以在此基础上添加新方法和成员变量来满足需求。
当创建一个类时,总是在继承。Java中的类没有显式的继承任何类,则默认继承Object类,Object类是Java语言提供的根类,也就是说,一个对象与生俱来就有Object类当中的所有特征。
注意
子类拥有父类的所有属性和方法是对的,只不过父类的私有属性和方法,子类是无法直接访到的。即只是拥有,但是无法使用。(这里不考虑Java反射机制)但是如果子类中公有的方法影响到了父类私有属性,那么私有属性是能够被子类使用到的。
不能被继承的成员父类:构造方法,构造函数。但是子类可以通过super()显示父类的构造函数。
如上图所示,动物继承生物类,老虎又继承动物类。从这个例子可以看出:越往上的类越抽象,越往下的类越具体。
继承规则
Java只支持单继承和多层继承,不允许多重继承
一个类可以被多个子类继承,一个类只能继承一个父类(直接父类),使用extends关键字
子父类是相对的概念
子类直接继承的父类,称为直接父类;间接继承的父类称为间接父类。
子类继承父类以后,就获取了直接父类以及所有间接父类中声明的属性和方法
代码实例
class Biology{ //生物类 String name; int age; } class Animal extends Biology{//动物类继承了生物类,生物类是动物类的直接父类 } class Plant extends Biology{//植物类继承了生物类,生物类是植物类的直接父类 } class Tiger extends Animal{//老虎类继承了动物类,动物类是老虎类的直接父类,生物类是老虎类的间接父类 } class Tree extends Plant{//树类继承了植物类,植物类是树类的直接父类,生物类是植物类的间接父类 }
方法重写
在子类中,可以根据需要对从父类中继承来的方法进行方法重写。重写以后,当子类对象调用与父类的同名同参数的方法时,优先调用子类重写的方法。
当子类调用属性和方法的时候,如果自己类里面有该属性和方法,肯定先调用自己的,如果自己类里面没有,就去父类(先直接父类/再间接父类)找,一直找到Object类为止。
方法重写有如下要求:
子类重写的方法必须和父类被重写的方法具有相同的方法名称、参数列表;
子类重写的方法的返回值类型不能大于父类被重写方法的返回值类型
即:
1.父类被重写的方法的返回值类型是void,则子类重写的方法的返回值类型只能是void。
2.父类被重写的方法的返回值类型是A类型,则子类重写的方法的返回值类型可以使A类或A类的子类。
3. 父类被重写的方法的返回值类型是基本数据类型(比如double),则子类重写的方法的返回值类型必须是相同的基本数据类型。
子类重写的方法使用的访问权限不能小于父类被重写的方法的访问权限
子类方法抛出的异常不能大于父类被重写方法的异常
子类能重写的都是非static的方法
思考:如果父类有个方法是private访问权限,在子类中将此方法声明为default访问权限,这个叫方法重写吗?达咩,当然不是。
super关键字
在Java类中,使用super调用父类中的指定操作。可以访问父类中的构造器、属性和成员方法。
我们需要掌握的内容:
super的三种语法格式:访问父类构造器(必须放构造函数中的第一行):super()或super(参数);访问父类属性:super.属性;访问父类方法:super.方法名()。
我们可以在子类的方法或构造器中,通过使用super.或super(),显式地调用父类中声明的属性/方法或构造器。通常情况下,我们习惯省略‘super.’。
特殊情况,若想在子类中调用父类的同名属性或被重写方法时,必须显式地使用'super.'。
子类中所有的构造器默认都会访问父类中空参数的构造器。
当父类中没有空参数的构造器时,子类的构造器必须通过super(参数列表)语句指定父类中相应的构造器,必须放在构造器的首行。目的在于在创建子类对象的时候,先初始化父类。
如果类里面有n个构造器,那么可以调用n-1次,至少1次是调父类的。
this()与super()不能同时出现,在构造器中,必须二选一,且只能出现在第一行。
结论:在java语言中,不管new什么对象,最后Object类中的无参构造方法是一定会执行的。
代码举例:
public class JavaTest { public static void main(String[] args) { Chinese cn=new Chinese(); cn=new Chinese("I 'm Chinese!"); cn=new Chinese("I 'm Chinese!",18); cn.sout(); } } class Person{ int id=431234566; String name; public Person(){} public Person (String name){ this.name=name; } public void sout(){ System.out.println("这是父类中的输出方法1"); } } class Chinese extends Person{ public Chinese(){ super(); //调用父类无参构造方法,这个子类每个构造器都会默认调用的,可不写 } public Chinese(String name){ super(name);//调用父类有参构造方法 } public Chinese(String name,int age){ this(name);//通过this去调用构造器中的super方法 System.out.println("父类中的id"+super.id);//调用父类的属性 } @Override public void sout() { System.out.println("这是子类中的输出方法!"); super.sout();//调用父类的sout方法 } }
输出结果是
父类中的id431234566
这是子类中的输出方法!
这是父类中的输出方法1
super与this的区别
super()函数在子类构造函数中调用父类的构造函数时使用,而且必须要在构造函数的第一行。
this()函数调用本类中另一种形成的构造函数。this()只能用在构造函数中,并且也只能在第一行。
super()和this()都指的是对象,不能同时出现在构造函数里,只能二选一,均不可在static环境中使用。
super:引用当前对象的父类中的成员。语法格式:super.属性名/方法名()
this:代表当前对象名。this是对象的隐藏属性 (本质就是一个普通的成员变量),和其他non-static 属性一样,在创建对象的时候会为每个新对象分配该对象的专属成员变量(this就是其中一个),this这个成员变量存储在堆内存中,该变量的值是所属对象在堆内存的地址。
this代表本类对象的引用,super代表父类的内存空间的标识。
从本质上来讲,this是一个面向对象的指针,然后super是一个Java关键字。
继承的好处:
提高代码复用性,减少代码冗余
便于功能扩展
为多态性的使用,提供了前提
继承也存在一些缺点,继承的类与类之间的耦合度非常高,不利于代码的扩展。
本文作者为BUG之神,转载请注明。