目录
一、前言
二、继承
(一)继承概念
(二)继承的语法
(三)父类成员访问
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类,进而实现代码复用。
(一)继承概念
(二)继承的语法
修饰符 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
}
}
结论:在子类方法中或者通过子类对象访问成员时 :1.如果访问的成员变量子类中有,优先访问自己的成员变量。2.如果访问的成员变量子类中无,则访问父类继承下来的,如果父类也没有定义,则编译报错。3.如果访问的成员变量与父类中成员变量同名,则优先访问自己的。4. 成员变量访问遵循就近原则,自己有优先自己的,如果没有则向父类中找 。
2.子类中访问父类的成员方法
Tips:1.成员方法没有同名时,在子类方法中或者通过子类对象访问方法时,则优先访问自己的,自己没有时,再到父类中找,如果父类中也没有则报错。2.通过子类对象访问父类与子类中不同名方法时,优先在子类中找,找到则访问,否则在父类中找,找到则访问,否则编译报错。
3.通过派生类对象访问父类与子类同名方法时,如果父类和子类同名方法的参数列表不同 ( 重载 ) ,根据调用方法适传递的参数选择合适的方法访问,如果没有则报错。
(四)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关键字
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中多态的知识点,感谢大家的支持与鼓励,我们下次再见!