继承是面向对象的三大特点之一。
那么,何为继承?
一个类的对象可以使用另一个类的对象中的成员,这种关系就称之为继承。
一:继承格式
继承关键字extends。
/** * 人类 */ class person { } /** * 学生类 */ class student extends person { }
二:继承的优缺点
优点
1:提高了代码的复用性
2:让类与类之间产生了继承的关系,这是构成多态的前提条件。
3:减少代码冗余,增强类的功能扩展性。
缺点
提高了代码的耦合性。在开发中我们遵循:高内聚,低耦合的原则。
高内聚:指一个类的功能越强越好
低耦合:指一个类的关系越少越好
三:继承的特点
1:java只支持单继承,不可以多继承。
/** * 父亲类 */ class fu { } /** * 儿子类 */ class zi extends fu { }
2:java类可以多层继承
/** * 爷爷类 */ class ye { } /** * 父亲类 */ class fu extends ye { } /** * 儿子类 */ class zi extends fu { }
3:java类不支持循环继承
/** * 爷爷类 */ class ye extends zi { } /** * 父亲类 */ class fu extends ye { } /** * 儿子类 */ class zi extends fu { }
这样写是不可以的。
四:继承后:成员变量、成员方法的访问特点
1:子类不能继承父类中被private关键字所修饰的成员变量和成员方法。
2:子类不能继承父类的构造方法。
3:在子类方法中访问成员(成员变量、成员方法)满足:就近原则,先子类局部范围找 然后子类成员范围找 然后父类成员范围找,如果父类范围还没有找到则报错。
如果子父类中,出现了重名的成员,会优先使用子类的,此时如果一定要在子类中使用父类的怎么办? 可以通过super关键字,指定访问父类的成员。
五:方法重写
Java子类重写父类方法标识:@Override
重写方法的名称、形参列表必须与被重写方法的名称和参数列表一致。
私有方法不能被重写。
子类重写父类方法时,访问权限必须大于或者等于父类 (暂时了解 :缺省 < protected < public)
子类写一个与父类申明一样的方法覆盖父类的方法。 @Override注解可以校验重写是否正确,同时可读性好。
重写方法的名称和形参列表应该与被重写方法一致。 私有方法不能被重写。
重写父类的静态方法会报错的。
public class T06 { public static void main(String[] args) { person fu = new person(); student stu = new student(); fu.drink(); stu.drink(); } } /** * 人类 */ class person { public void drink() { System.out.println("父类喝水"); } } /** * 学生类 */ class student extends person { @Override public void drink() { System.out.println("子类喝水"); } }
输出:
父类喝水
子类喝水
六:this、super关键字
关键字 | 访问成员变量 | 访问成员方法 | 访问构造方法 |
this | this.成员变量 访问本类成员变量 | this.成员方法(…) 访问本类成员方法 | this(…)访问本类构造方法 |
super | super.成员变量 访问父类成员变量 | super.成员方法(…) 访问父类成员方法 | super(…) 访问父类构造方法 |
我们先来看下方的代码:
package d0131; public class T05 { public static void main(String[] args) { student stu = new student(); stu.drink(); } } /** * 人类 */ class person { public int i = 1; public void drink() { System.out.println("父类喝水"); } } /** * 学生类 */ class student extends person { int i = 2; @Override public void drink() { int i = 3; System.out.println(i); System.out.println(i); System.out.println(i); } }
控制台输出:
3
3
3
那现在有一个小要求,要求控制台输出3/2/1,我们该如何实现呢?
这其中就需要使用到this以及super关键字。
代码如下所示:
public class T05 { public static void main(String[] args) { student stu = new student(); stu.drink(); } } /** * 人类 */ class person { public int i = 1; public void drink() { System.out.println("父类喝水"); } } /** * 学生类 */ class student extends person { int i = 2; @Override public void drink() { int i = 3; System.out.println(i); // 当前这个类的成员变量i System.out.println(this.i); // 父类的成员变量i System.out.println(super.i); } }
输出:
3
2
1
七:构造函数
1:子类的构造函数中,默认都加载了一次父类的构造函数,也就是super()
public class T01 { public static void main(String[] args) { zi zi1 = new zi(); zi zi2 = new zi("xh"); } } class fu { public fu() { System.out.println("我被调用了!"); } private String files; public String getFiles() { return files; } public void setFiles(String files) { this.files = files; } } class zi extends fu { /** * 无参构造方法 */ public zi() { // 默认就有一个super方法 // super(); } /** * 重载有参构造方法 * @param name */ public zi(String name) { // 默认就有一个super方法 // super(); } }
上边的程序,控制台输出:
我被调用了!
我被调用了!
为什么会有这样的现象呢?
因为有继承,说明子类可以使用父类的成员变量,那也就意味着父类的成员变量一定要有一直才可以被使用,所以在创建类对象的时候,会调用子类的构造方法,而子类的构造方法中会先去调用父类的构造方法,目的就是给父类的额成员变量默认初始化
2:子类的所有构造方法中,第一行要么是super(参数),要么是this(参数),他们不可以共存。并且子类中所有的构造方法中至少有一个构造方法里边调用的是super(参数)
class zi extends fu { /** * 无参构造方法 */ public zi() { // 默认就有一个super方法 // super(); this("xxx"); } /** * 重载有参构造方法 * @param name */ public zi(String name) { // 默认就有一个super方法 // super(); this(); } }
这样写是不行的。编译报错。死循环了属于是。
以上大概就是 java 继承的基本使用。
有好的建议,请在下方输入你的评论。