JAVASE面向对象-继承(继承特点,this与super关键字,方法重写以及final关键字)
程序员文章站
2022-03-26 16:51:53
1.继承的引入在生活中,有形形色色的继承,最常见的继承是一个家族财产的继承关系,儿子可以继承父亲的财产。在Java中也存在继承关系,Java中的继承是子类可以继承父类的成员(成员变量与成员方法)。Java中继承关系的语法为:用extends关键字来进行继承,让类与类之间产生继承关系。下面我们先用生活中一个简单的例子来引入Java中的继承关系:我们知道动物里面有很多类别,例如猫,狗之类的,都有一些共性的东西。例如吃饭,睡觉等。那么我们就可以将这些共性的东西向上抽取到Animal这个类中,在子类中直接...
1.继承的引入
在生活中,有形形色色的继承,最常见的继承是一个家族财产的继承关系,儿子可以继承父亲的财产。在Java中也存在继承关系,Java中的继承是子类可以继承父类的成员(成员变量与成员方法)。
Java中继承关系的语法为:
用extends关键字来进行继承,让类与类之间产生继承关系。
下面我们先用生活中一个简单的例子来引入Java中的继承关系:
我们知道动物里面有很多类别,例如猫,狗之类的,都有一些共性的东西。例如吃饭,睡觉等。那么我们就可以将这些共性的东西向上抽取到Animal这个类中,在子类中直接就会继承,可以大量的减少代码量,实现代码的实用性与维护性。
//父类:
public class Anmial {
//将子类共有的东西向上抽取到父类,以实现代码的复用性与维护性
public String name;
public int age;
public void eat(){
System.out.println("吃饭");
}
public void sleep(){
System.out.println("睡觉");
}
}
//子类:
public class Cat extends Anmial {
//子类中可以保留自己特有的方法
public void catchMouse(){
System.out.println("猫抓老鼠");
}
}
public class Dog extends Anmial {
public void lookDoor(){
System.out.println("小狗看门");
}
}
//测试类:
public class MyTest {
public static void main(String[] args) {
Cat cat = new Cat();
cat.name="胖橘";
cat.age=3;
System.out.println(cat.name);
System.out.println(cat.age);
cat.eat();
cat.sleep();
cat.catchMouse();
System.out.println("================");
Dog dog = new Dog();
dog.name="小强";
dog.age=5;
System.out.println(dog.name);
System.out.println(dog.age);
dog.eat();
dog.sleep();
dog.lookDoor();
}
}
运行的结果为:
胖橘
3
吃饭
睡觉
猫抓老鼠
================
小强
5
吃饭
睡觉
小狗看门
- 继承的利弊分析
继承的好处 | 继承的弊端 |
---|---|
提高了代码的复用性与维护性 | 让类与类之间产生了依赖的关系,增加了耦合性 |
继承是多态的前提,有了继承才能谈及多态 | 当依赖关系太过于紧密时,会违背软件的设计原则:高内聚,低耦合 |
让类与类之间有了继承关系 | 耦合性过高时,不利于软件后期的维护和扩展 |
2.继承的特点
- Java中继承语法:Java中只支持单继承,不支持多继承。可以支持多层继承
- Java中子类只能继承父类的非私有成员。私有成员,子类不能继承。
- 构造方法不参与继承
- 静态方法可以继承
//Object 是我们Java继承体系当中的顶层父类
//所有的类都是直接或间接继承自他。
public class MyTest2 extends Object{
public static void main(String[] args) {
/*Java中继承的语法特点
1.Java中只支持单继承
一个子类只能有一个父类,
一个父类是可以有多个子类。
不支持多继承。可以支持多层继承。
2.子类只能继承父类非私有的成员。私有的成员,子类不能继承。
3.构造方法,不参与继承。构造方法,在你初始化子类对象时,
会调用父类构造来完成父类数据的初始化。
4.静态方法也是可以继承的。*/
D d = new D();
d.hehe();
D.hehe();
}
}
class A extends Object{
//子类不能继承父类中的私有变量
private int a=10;
public void a(){
}
}
class B extends A{
int b=100;
//子类不能继承父类的私有方法
private void b(){}
}
class C extends B{
int c=70;
public void c(){}
public static void hehe(){
}
}
class D extends C{
}
}
- 当我们创建子类对象时,会先调用父类的构造方法的原因:当我们去创建子类对象时,子类会继承父类的一些数据,会先完成父类数据的初始化,然后初始化自己的数据
public class MyTest {
public static void main(String[] args) {
/*当我们创建子类对象时,会先调用父类的构造方法,为什么?
当我们去创建子类对象时,子类要继承父类的一些数据甚至还要去使用,
那如果子类的数据没有完成初始化,子类能继承吗?肯定不行。
所以当我们创建子类对象时,应该先完成父类数据的初始化,
然后在初始自己的数据。
*/
/*创建子类成员变量时,会先调用父类的构造方法,
然后在调用子类构造方法
*/
Zi zi = new Zi();
}
}
class Fu extends Object{
int a=20;
public Fu(){
super();
System.out.println("父类的构造方法执行了");
}
}
class Zi extends Fu{
public Zi(){
super(); //调用父类的空参构造
System.out.println("子类的构造方法执行了");
}
}
3.this 、super关键字
super关键字 |
---|
super:表示父类的空间标识,可以简单理解为父类的一个引用,使用super可以调用父类的数据 |
super.变量名:调用父类的变量 |
super.方法名():调用父类的方法 |
super():调用父类的空参构造 |
super(有参):调用父类的有参构造 |
this关键字 |
---|
this:表示本类的一个引用,谁调用这个方法,方法中的this就代表谁 |
this.变量名:调用本类的变量 |
this.方法名():调用本类的方法 |
this():调用本类的空参构造 |
this(有参):调用本类的有参构造 |
public class MyTest {
public static void main(String[] args) {
ZZ zz = new ZZ();
zz.ziHeHe(140);
}
}
class FF{
int num=20;
private int bb=250;
public int cc=1405;
public void fuShow(){
System.out.println(num+"父类的方法");
}
public int getBB(){
return this.bb;
}
}
class ZZ extends FF{
int z=100;
int num=800;
public void ziHeHe(int num) {
/*
变量访问的就近原则。
* 当我们在方法中访问一个变量的时候,先从局部范围找,
找到就使用,如果没找到,去本类的成员范围找,找到就使用,
* 如果没找到,会去父类的成员范围找,找到就使用
* 局部变量和成员变量以及父类的成员变量重名问题,
可以使用 this super 来区分
* */
System.out.println(num);//140
System.out.println(this.num);//800
System.out.println(super.num);//20
System.out.println(cc);
}
public void ziShow(){
System.out.println(this.z);
System.out.println(this.num);
System.out.println(super.num);
this.fuShow();
super.fuShow();
// System.out.println(super.bb); 报错
int bb = this.getBB();
int bb1 = super.getBB();
System.out.println(bb);
System.out.println(bb1);
}
}
4.方法重写
在继承关系中,当子类与父类存在一模一样的方法,可以进行方法重写。
- 方法重写:子类中出现与父类一模一样的方法(方法名,参数列表以及返回值的类型),也称为方法重写或者方法覆盖。
- 子类会覆盖父类的方法,实际运行时,运行的是子类重写过的方法
- 方法重写的机制:一个父类会有多个子类,父类里面抽取的是所有子类共性的功能,但每个子类对于共性功能的具体实现,存在差异。
- 子类方法重写的目的:就是对父类功能实现不满意,想要根据自己的需求,进行重写与扩展
4.1 方法重写(功能重写)
//父类
public class Animal {
//对于子类*性功能进行提取
public void eat() {
System.out.println("吃饭");
}
public void sleep() {
System.out.println("睡觉");
}
}
//子类
public class Cat extends Animal{
public void catchMouse(){
System.out.println("抓老鼠");
}
public void eat(){
System.out.println("猫爱吃小鱼干");
}
public void sleep(){
System.out.println("猫喜欢白天睡觉");
}
}
public class Dog extends Animal{
public void lookDoor(){
System.out.println("狗看门");
}
public void eat(){
System.out.println("狗吃骨头");
}
}
//测试类
public class MyTest {
public static void main(String[] args) {
Cat cat = new Cat();
cat.eat();
cat.sleep();
System.out.println("=====================");
Dog dog = new Dog();
dog.sleep();
dog.eat();
}
}
输出的结果为:
猫爱吃小鱼干
猫喜欢白天睡觉
=====================
睡觉
狗吃骨头
4.2 方法重写(功能扩展)
- 对于某部分代码满意,还想扩展,也可以通过方法重写来实现
//父类:手机类
public class Phone {
public Phone() {
System.out.println("构造方法执行了");
}
public void call() {
System.out.println("打电话 ");
}
public void send() {
System.out.println("发短信");
}
}
//子类:Iphone手机
public class Iphone extends Phone{
public void palyGame(){
System.out.println("玩游戏");
}
@Override //注解
// @Override 这个注解的作用,是用来检测此方法是不是重写父类的方法
public void call() {
super.call(); //沿袭父类的功能
System.out.println("高清视频通话");
}
}
//测试类:
public class MyTest {
public static void main(String[] args) {
Iphone iphone = new Iphone();
iphone.call();
iphone.send();
iphone.palyGame();
}
}
输出的结果为:
打电话
高清视频电话
发短信
4.2 方法重写的注意事项
方法重写的注意事项 |
---|
父类的私有方法,子类不能进行重写(因为父类的私有方法,子类都不能继承,就更不能进行重写 |
父类的构造方法不能重写(构造方法不参与继承) |
静态方法不参与重写 |
子类在重写父类方法时,方法的权限修饰符,不能比父类的低,可以与父类的权限修饰符保持一致(权限:public>protected>缺省>私有) |
public class MyTest {
public static void main(String[] args) {
//方法重写时,需要注意的事项。
//1.父类私有的方法,子类不能重写,私有方法,子类不能继承
//2.父类构造方法,不能重写,构造方法没有继承一说。
//3.子类在重写父类方法时,方法的权限修饰符,
// 不能比父类的低可以跟父类的一样,或者比父类的高
//public>protected>缺省的>private
//4.静态方法,不参与重写
Father.haha();
Son son = new Son();
son.haha();
Son.haha();
}
}
class Father{
private void show(){
}
protected void hehe(){
}
public static void haha(){
System.out.println("父类的静态方法");
}
}
class Son extends Father{
@Override
protected void hehe() {
}
//@Override 静态方法不参与重写
public static void haha() {
System.out.println("子类的静态方法");
}
}
5.final关键字
- final关键字是最终的意思,可以修饰类,变量,成员方法。
final修饰特点 |
---|
修饰类: 被修饰类不能被继承 |
修饰方法: 被修饰的方法不能被重写 |
修饰变量: 被修饰的变量不能被重新赋值,因为这个量其实是一个常量 |
public class MyTest {
//公共的静态常量
public static final double AA=3.14; //自定义常量
public static void main(String[] args) {
//final 最终的,可以修饰成员变量,局部变量,形参,也可以修饰方法,也可以修类
//修饰变量,此变量为一个常量,既然为常量,常量的值就不能再次被改变。
//自定义常量,常量名一般建议大写
final int NUM=100;
//NUM=200; //重新赋值,报错,常量不能再次赋值
System.out.println(NUM);
double aa = MyTest.AA;
System.out.println(aa);
BB bb = new BB();
System.out.println(bb);
bb=new BB();
System.out.println(bb);
System.out.println("============================");
final BB bb1 = new BB();
//final修饰的是基本类型,指的是值不能再次被改变。
//final修饰的是引用数据类型,指的是这个地址值,不能再次被改变
//final修饰方法,此方法,不能被子类重写,但是可以让子类继承去用
CC cc = new CC();
cc.show();
//final 修饰类,此类不能被继承
}
}
class BB{
public final void show(){
System.out.println("父类的final修饰的方法,子类不能重写,子类可以继承");
}
}
class CC extends BB{
/* @Override
public void show() {
}*/
}
//final修饰类,此类不能被继承
final class EE{
}
/*
class FF extends EE{
}
*/
本文地址:https://blog.csdn.net/qq_41537102/article/details/110225610
上一篇: POJ_1700(过河问题)
下一篇: MyBatisPlus--通用枚举