类和对象进阶 - 继承
1. 继承
1.1 继承解决了什么问题 ? java中如何实现继承 ?
对类的共性进行抽取 对代码进行复用 java中, 使用extends关键字 关联
查看代码
/* class Dog { public String name; public int age; public float weight; public void eat() { System.out.println(name + "正在吃饭"); } public void sleep() { System.out.println(name + "正在睡觉"); } } class Cat { public String name; public int age; public void eat() { System.out.println(name + "正在吃饭"); } public void sleep() { System.out.println(name + "喵叫"); } }*/ // 发现上述代码 有很多重复的地方 // 继承用来 复用代码 // class Animal { public String name; public int age; public void eat() { System.out.println(name + "正在吃饭"); } } class Dog extends Animal{ public String color; public void sleep() { System.out.println(name + "正在睡觉"); } } class Cat extends Animal{ public void sleep() { System.out.println(name + "喵叫"); } } public class Main { public static void main(String[] args) { Cat cat = new Cat(); cat.name = "小白"; System.out.println(cat.name); Dog dog = new Dog(); dog.name = "大黄"; System.out.println(dog.name); } }
1.2 子类继承父类什么 ? 子类对象如何存储 ?
子类继承父类的成员变量和方法,除了父类构造方法和父类中的静态成员
查看代码
class Animal { public String name; public int age; public static int id = 1; public void eat() { System.out.println(name + "正在吃饭"); } } class Dog extends Animal{ public String color; public void sleep() { System.out.println(name + "正在睡觉"); } } public class Main { public static void main(String[] args) { Dog dog = new Dog(); dog.name = "a"; dog.age = 2; } }
分为两块 一部分存储父类的 一部分存储子类自己的
1.3 访问优先级
子类与父类存在同名成员时,优先访问子类自己的成员变量/方法如果访问的成员方法子类中无,则访问父类继承下来的如果父类也没有定义,则编译报错
查看代码
class Base { public int a = 1; public int b = 2; public void test() { System.out.println("Base::test()"); } } class Derived extends Base { public int a = 10; public int c = 3; public void test() { System.out.println("Derived::test()"); } public void test2() { System.out.println("Derived::test2()"); } public void test(int a) { System.out.println(a); } public static void main(String[] args) { Derived derived = new Derived(); // 存在同名成员时,优先访问子类自己的成员变量 / 方法 // 访问的成员方法子类中无,则访问父类继承下来的 // 如果父类也没有定义,则编译报错 System.out.println(derived.a); derived.test(); derived.test2(); } }
1.4 super关键字
super 表示父类数据对象的引用, 用来指定访问 父类成员
this 表示对象的引用
查看代码
class Base { public int a = 1; public int b = 2; public void test() { System.out.println("Base::test()"); } } class Derived extends Base { public int a = 10; public int c = 3; public void test() { System.out.println("Derived::test()"); } public void test2() { System.out.println("Derived::test2()"); } public void test(int a) { System.out.println(a); } public void method() { // super this System.out.println(this.a); System.out.println(super.a); } public static void main(String[] args) { Derived derived = new Derived(); derived.method(); } }
super关键字总结与注意事项
总结:
1. super用来在子类中 指定访问父类成员变量和方法 因为this引用优先访问子类自己的成员
2. super加点号 访问父类成员变量和方法
3. super(..) 访问父类的构造方法
注意事项:
1. super只能在非静态方法中使用
2. 在子类构造方法中调用super(...)初始化父类成员,必须放在第一行
super与this 相同点和不同点
相同点:
1. 都是Java中的关键字
2. 只能在类的非静态方法中使用
3. 在构造方法中调用时,必须是构造方法中的第一条语句,并且不能同时存在
不同点:
1. this是当前对象的引用 —— super 是从父类继承下的部分成员变量的引用 如图
2. 在非静态成员方法中,this优先访问子类自己的成员变量和属性 如果找不到子类成员 再去访问父类成员 —— super 指定访问父类的成员
3. 在子类构造方法中,this(...)用于调用子类自己的构造方法,super(...)用于调用父类构造方法,两种调用不能同时在构造方法中出现 因为this() super()都需要占用第一行
4. 子类构造方法中一定会存在super(...)的调用,用户没有写编译器也会增加,但是this(...)调用用户不写则没有
1.5 子类对象如何初始化 ?
首先调用父类构造方法给子类对象中的父类成员进行初始化
然后再初始化子类自己的成员
class Animal { public String name; public int age; public void eat() { System.out.println(name + "正在吃饭"); } public Animal(String name,int age) { this.name = name; this.age = age; } } class Dog extends Animal{ public String color; public Dog(String name,int age) { // 在子类自己成员变量初始化前 必须先调用父类构造初始化子类对象中的父类成员 super(name,age); this.color = "黑色"; } public static void main(String[] args) { Dog dog = new Dog("a",1); System.out.println(dog.name); } }
为什么自己没写构造,编译器不报错 ?
class Animal { public String name; public int age; public void eat() { System.out.println(name + "正在吃饭"); } // 默认生成 Animal构造 /*public Animal() { }*/ } class Dog extends Animal{ public String color; // 默认生成 Dog构造 /*public Dog() { 自动生成 super() super(); }*/ public static void main(String[] args) { Dog dog = new Dog(); } }
1.6 继承关系上的执行顺序
父类的静态,子类的静态,父类的实例,父类的构造,子类的实例,子类的构造
class Animal { public String name; public int age; public Animal() { System.out.println("Animal()"); } static { System.out.println("Animal::static{}"); } { System.out.println("Animal::{ }"); } public Animal(String name, int age) { this.name = name; this.age = age; System.out.println("Animal(String name, int age)"); } public void eat() { System.out.println(this.name+"正在吃....."); } } class Dog extends Animal { public String color; public Dog() { //super(); System.out.println("Dog()"); } static { System.out.println("Dog::static{}"); } { System.out.println("Dog::{ }"); } public static void main(String[] args) { Dog dog = new Dog(); } }
1.7 java继承关系与final修饰类
2. 访问修饰限定符
class Person implements Cloneable { public String name; public int age; public Person(String name, int age) { this.name = name; this.age = age; } @Override protected Object clone() throws CloneNotSupportedException{ // 一定得在子类方法中, 调用protected修饰的父类成员 return super.clone(); } } public class Test { public static void main(String[] args) throws CloneNotSupportedException { Person person1 = new Person("a",1); Person p2 = (Person) person1.clone(); System.out.println(p2.name); } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!