温馨提示:这篇文章已超过463天没有更新,请注意相关的内容是否还可用!
摘要:本篇内容主要介绍了JavaSE中的继承和多态概念。继承是面向对象编程的三大特性之一,它允许子类继承父类的属性和方法,实现代码复用。多态则是允许一个接口或方法在多种不同的上下文中表现出不同的行为。通过继承和多态,Java可以实现代码的灵活性和可维护性。上篇内容主要讲解了继承的基本概念以及如何使用Java实现多态性,为后续深入学习JavaSE打下坚实的基础。
目录
一、前言
二、继承
(一)继承概念
(二)继承的语法
(三)父类成员访问
1.子类中访问父类的成员变量
1.1子类和父类不存在同名成员变量
1.2子类和父类成员变量同名
2.子类中访问父类的成员方法
(四)super关键字
(五)子类构造方法
(六)super和this
(七)代码块执行顺序
(八)final关键字
1. 修饰变量或字段,表示常量(即不能修改)
2. 修饰类:表示此类不能被继承
3. 修饰方法:表示该方法不能被重写
三、总结
一、前言
各位小伙伴们大家好,今天蜡笔小欣将继续带来大家一起去遨游Java的知识海洋世界,掌握Java中的继承。话不多说,开始我们今天的学习。
二、继承
public class Dog { String name; int age; float weight; public void eat() { System.out.println(name + "正在吃饭"); } public void sleep() { System.out.println(name + "正在睡觉"); } public void bark() { System.out.println(name + "汪汪汪"); } } public class Cat{ String name; int age; float weight; public void eat(){ System.out.println(name + "正在吃饭"); } public void sleep() { System.out.println(name + "正在睡觉"); } public void mew(){ System.out.println(name + "喵喵喵~~~"); } }
上面这个Dog类和Cat类有大量重复的部分,我们可以将这些共同点共性抽取,放在一个Animal类,进而实现代码复用。
(一)继承概念
继承 是 面向对象程序设计,使代码可以复用 的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加新功能 ,这样产生新的类,称 派生类 。继承呈现了面向对象程序设计的层次结构, 体现了由简单到复杂的认知过程。继承主要解决的问题是:共性的抽取,实现代码复用 。(二)继承的语法
在 Java 中如果要表示类之间的继承关系,需要借助 extends 关键字,具体如下: 修饰符 class 子类 extends 父类 {// …
}
因此我们可以创建一个Animal类,将Dog类和Cat类的共同点放在Animal类里面,具体代码如下:
class Animal{ String name; int age; float weight; public void eat(){ System.out.println(name + "正在吃饭"); } public void sleep(){ System.out.println(name + "正在睡觉"); } }
我们再通过继承,让Dog类和Cat类继承Animal类里面的成员变量和方法,具体修改如下:
class Animal { String name; int age; float weight; public void eat() { System.out.println(name + "正在吃饭"); } public void sleep() { System.out.println(name + "正在睡觉"); } } class Dog extends Animal { public void bark() { System.out.println(name + "汪汪汪"); } } class Cat extends Animal { public void mew() { System.out.println(name + "喵喵喵~~~"); } }
Tips:
1. 子类会将父类中的成员变量或者成员方法继承到子类中,
2.子类继承父类之后,必须要新添加自己特有的成员,体现出与基类的不同,否则就没有必要继承。
(三)父类成员访问
1.子类中访问父类的成员变量
1.1子类和父类不存在同名成员变量
class Base { int a; int b; } public class Derived extends Base { int c; public void method() { a = 10; // 访问从父类中继承下来的a b = 20; // 访问从父类中继承下来的b c = 30; // 访问子类自己的c } }
1.2子类和父类成员变量同名
class Base { int a; int b; int c; } public class Derived extends Base { int a; //与父类中成员a同名,且类型相同 char b; //与父类中成员b同名,但类型不同 public void method() { a = 100; // 访问父类继承的a,还是子类自己新增的a? b = 101; // 访问父类继承的b,还是子类自己新增的b? c = 102; // 子类没有c,访问的肯定是从父类继承下来的c // d = 103; // 编译失败,因为父类和子类都没有定义成员变量d } }


2.子类中访问父类的成员方法
Tips: 1.成员方法没有同名时,在子类方法中或者通过子类对象访问方法时,则优先访问自己的,自己没有时,再到父类中找,如果父类中也没有则报错。2.通过子类对象访问父类与子类中不同名方法时,优先在子类中找,找到则访问,否则在父类中找,找到则访问,否则编译报错。
3.通过派生类对象访问父类与子类同名方法时,如果父类和子类同名方法的参数列表不同 ( 重载 ) ,根据调用方法适传递的参数选择合适的方法访问,如果没有则报错。(四)super关键字
Java给我们 提供了 super 关键字,该关键字主要作用:在子类方法中访问父 类的成员。 super的三个用法: 1.super.成员变量; 访问父类普通成员变量 2.super.方法(); 访问父类普通成员方法 3.super (); 调用父类的构造方法下面我举个例子,让大家更好地理解:
我们先定义一个父类Student类,具体代码如下:
class Student { public String name; public int age; public void method1(){ System.out.println("这是学生类的method1方法"); } public void method2() { System.out.println("这是学生类的method2方法"); } }
接着我们定义子类Stu继承父类Student ,在这个子类里有自己的成员变量和方法,具体代码如下:
public class Stu extends Student { public String name;//与父类中的成员变量同名且类型相同 public double age;//与父类中的成员变量同名但类型不相同 public void method1(int a) { System.out.println("这是Stu类中的method1方法"); } public void method3() { name = "张三";//对于同名的成员变量,直接访问时,访问的都是子类 age = 20; super.name = "李四";//访问父类的成员变量时,需要借助super关键字 super.age = 18;//super是获取子类对象中从父类继承下来的部分 //父类和子类中构成重载的方法 method1();//访问父类的method1方法 method1(10);//访问子类中带一个参数的method1方法 } }
使用super关键字时要注意:
1.只能在非静态方法中使用,
2.在子类方法中,访问父类的成员变量和方法, 3.对于父类的private成员变量,子类会继承继承该成员变量,但不可以访问, 4.java不支持多继承,即一个类只能继承一个父类。(五)子类构造方法
子类对象构造时,需要先调用基类构造方法,然后执行子类的构造方法。
下面给大家演示一下:
class Student { public String name; public int age; public void study() { System.out.println("正在学习"); } }
我们首先定义一个父类Student,包含两个成员变量和一个成员方法。
public class Stu extends Student { public String gender; }
紧接着我们再定义一个子类Stu继承自父类Student,子类中新增一个成员变量gender。
public class Stu extends Student { public String gender; public Stu() { this.gender = gender; } }
当我们想通过构造方法在子类中给gender成员变量初始化,就必须先给基类中继承下来的成员变量初始化,然后初始化自己的成员变量。
class Student { public String name; public int age; public Student(String name, int age) {//父类的构造方法是带有两个参数的 this.name = name; this.age = age; } public void study() { System.out.println("正在学习"); } } public class Stu extends Student { public String gender; //子类构造方法必须带有明确的基类的参数,然后通过super关键字访问父类成员变量 public Stu(String name, int age) { super(name, age);//super必须写在构造方法的第一行 //this(name,age);//super()和this()不能同时出现 this.gender = gender; } }
当父类的构造方法带有参数,那我们需要给子类显式定义构造方法,并且在子类的构造方法中选择合适的父类构造方法进行调用,否则会编译失败。
(六)super和this
super和this的共同点:
1. super和this都是Java中的关键字。
2. 它们只能在类的非静态方法中使用,用来访问非静态成员方法和字段。
3. 在构造方法中调用时,必须是构造方法中的第一条语句,而且它们不能同时存在。
super和this的不同点:
1. this是当前对象的引用,当前对象即调用实例方法的对象,super相当于是子类对象中从父类继承下来部分成员的引用。
2. 在非静态成员方法中,this用来访问本类的方法和属性,super用来访问父类继承下来的方法和属性。
3. 在构造方法中:this(...)用于调用本类构造方法,super(...)用于调用父类构造方法,两种调用不能同时在构造方法中出现。
4. 构造方法中一定会存在super(...)的调用,用户没有写编译器也会增加,但是this(...)用户不写则没有。
(七)代码块执行顺序
我们通过下面这个代码来了解继承关系上代码块的执行顺序。
class Student { public String name; public int age; public Student(String name, int age) {//父类的构造方法是带有两个参数的 this.name = name; this.age = age; System.out.println("Student:构造方法执行"); } { System.out.println("Student:实例代码块执行"); } static { System.out.println("Student:静态代码块执行"); } } class Stu extends Student { public Stu(String name, int age) { super(name, age); System.out.println("Stu:构造方法执行"); } { System.out.println("Stu:实例代码块执行"); } static { System.out.println("Stu:静态代码块执行"); } } public class Test { public static void main(String[] args) { Stu student1 = new Stu("张三", 19); System.out.println("==========================="); Stu student2 = new Stu("李四", 20); } public static void main1(String[] args) { Student student3 = new Student("王五", 10); System.out.println("============================"); Student student4 = new Student("赵六", 20); } }
运行结果如下:
Tips:
1、父类静态代码块优先于子类静态代码块执行,且是最早执行。
2、父类实例代码块和父类构造方法紧接着执行。
3、子类的实例代码块和子类构造方法紧接着再执行。
4、第二次实例化子类对象时,父类和子类的静态代码块都将不会再执行。
(八)final关键字
final 关键可以用来修饰变量、成员方法以及类。1. 修饰变量或字段,表示常量(即不能修改)
public class Test { public static void main(String[] args) { final int age = 18; age=20;//编译错误 } }
由于变量age被final修饰,导致变量age变为常量,修改不了。
2. 修饰类:表示此类不能被继承
final class Person { public String name; public int age; } class Student extends Person {//编译错误,无法继承Person类 public void study() { System.out.println("正在学习!"); } }
上面代码的父类Person被final修饰,导致子类Student无法继承Person,无法继承父类中的成员变量。
3. 修饰方法:表示该方法不能被重写
class Person { public String name; public int age; final void eat() { System.out.println("正在吃饭!"); } } class Student extends Person {//编译错误,无法继承Person类 public void eat() {//编译错误,无法重写eat方法 System.out.println("正在吃面包"); } public void study() { System.out.println("正在学习!"); } }
因为父类Person中的eat方法被final修饰,导致子类Student不能对eat方法进行重写,所以编译错误。
三、总结
继承允许一个类(子类)继承另一个类(父类)的属性和方法。通过继承,子类可以获得父类的属性和方法,同时还可以定义自己的属性和方法,从而实现代码的复用和扩展。继承的关键字是extends,子类通过extends关键字来继承父类。通过继承,子类可以重写父类的方法,从而实现多态性。此外,Java中只支持单继承,即一个类只能有一个直接的父类,但可以有多个间接的父类。继承可以帮助我们更好地组织和管理代码,实现代码的层次结构,使代码更加清晰和易于理解。但如果我们过度使用继承也会导致代码的耦合性增加,不利于代码的重构和扩展。
以上就是本期分享的全部内容,希望本期的内容能够对大家有所帮助,下次蜡笔小欣再跟大家分享Java中多态的知识点,感谢大家的支持与鼓励,我们下次再见!
还没有评论,来说两句吧...