11Java基础之继承
继承
- java中提供了一个extends的关键字,意思是“拓展”。用这个关键字可以让一个类和另一个类建立父子关系。
继承的特点:
子类能直接继承父类的非私有成员(成员变量,成员方法)
JAVA中类只有单继承,没有多继承。一个儿子只能有一个爸爸,一个爸爸可以有多个儿子。
继承是类和类之间的一种关系。除此之外,类和类之间的关系还有依赖、组合、聚合等。
继承关系的两个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字extend来表示。
继承后对象的创建
- 子类的对象是由子类和父类 以及多张设计图一起创建的。
- 对象能直接访问什么成员,是由父类这多张设计图共同决定的,多张设计图在外暴露了什么成员,对象就可以访问什么成员。
注意:
- 子类继承父类,就会拥有父类的全部方法。
- 父类中私有的东西,子类无法继承。
- 在IDEA工具中,父类或者继承的子类,在类名上按Ctrl+H快捷键可以看到类的继承关系。
父类:
public class A {
public int i;
public void print(){
System.out.println("我是A类");
}
private int j;
private void print1(){
System.out.println("我是A类的私有方法");
}
}
子类:
public class B extends A{
private int k;
public void print2(){
// 继承特点:子类只能继承父类的非私有成员
System.out.println(i);
print();
// 继承特点:子类不能继承父类的私有成员
// System.out.println(j); // 报错
// print1(); // 报错
}
}
main方法:
public static void main(String[] args) {
// 子类对象的创建特点:会由子类和父类等多张设计图共同创建出子类对象,但是能访问什么看权限。
B b = new B();
System.out.println(b.i);
// System.out.println(b.j); // 报错
// System.out.println(b.k); // 报错
b.print();
// b.print1(); // 报错
b.print2();
}
}
- 继承的好处就是可以减少重复代码的编写
案例:
父类:
public class People {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
子类:
public class Teacher extends People{
private String skill;
public String getSkill() {
return skill;
}
public void setSkill(String skill) {
this.skill = skill;
}
}
main方法:
public static void main(String[] args) {
Teacher t = new Teacher();
t.setName("波妞");
t.setSkill("程序员鼓励师,哄程序员加班~");
System.out.println(t.getName());
System.out.println(t.getSkill());
}
输出结果:
波妞
程序员鼓励师,哄程序员加班~
- teacher类继承了people类,所以它可以调用父类中的方法,也可以调用自身的方法。
继承的相关注意事项
- 权限修饰符
- 权限修饰符,是用来限制类中的成员(成员变量、成员方法、构造器、代码块……)能够被访问的范围。
- 权限修饰符有如下几种:
- private:只能本类
- 缺省:本类、同一个包中的类
- protected:本类、同一个包中的类、子孙类中
- public:任意位置
案例:
父类:
public class Father {
// 1. private,私有的,只能在本类中访问
private void privateMethod() {
System.out.println("private");
}
// 2. 缺省,只能在本类,同一包下的其他类中访问
void defaultMethod() {
System.out.println("default:缺省");
}
// 3. prodected,子类权限,只能在本类,同一个包下的类,子孙类中访问
protected void protectedMedhod() {
System.out.println("protected");
}
// 4. public,公共权限,可以在任意类中访问
public void publicMedhod() {
System.out.println("public");
}
public static void main(String[] args) {
Father f = new Father();
f.privateMethod();
f.defaultMethod();
f.protectedMedhod();
f.publicMedhod();
}
}
**同一个类中,所有的修饰的方法都可以调用。**
同一个包,不同的类调用
public class Demo01 {
public static void main(String[] args) {
Father f = new Father();
//f.privateMethod(); // 报错
f.defaultMethod();
f.protectedMedhod();
f.publicMedhod();
}
}
**除了私有修饰的方法不能调用,剩下的都可以调用。**
-------------------------------------------------
不同包的类
public class Demo02 {
public static void main(String[] args) {
Father f = new Father();
// f.privateMethod(); // 报错
// f.defaultMethod(); // 报错
// f.protectedMedhod();// 报错
f.publicMedhod();
}
}
**除了公共修饰的方法,别的修饰的方法都不能调用。**
-----------------------------------------------
不同包的子类
public class Son extends Father {
public void print(){
// privateMethod(); // 报错
// defaultMethod(); // 报错
protectedMedhod();
publicMedhod();
}
public static void main(String[] args) {
Son s = new Son();
// s.privateMethod(); // 报错
// s.defaultMethod(); // 报错
s.protectedMedhod();
s.publicMedhod();
}
}
**除了私有和缺省修饰的方法,别的都可以调用。**
# 单继承
- Java是单继承的,Java中的类不支持多继承,但是支持多层继承。
**案例:**
``` java
// 目标:搞清楚继承的特点
public class Test {
public static void main(String[] args) {
}
}
//1. Java是单继承的,一个类只能有一个父类
//2. Java不支持多继承
class A{ }
class B{ }
//class C extends A,B{} //报错
//3. Java支持多层继承
class C extends A{}
class D extends C{}
- 为何Java中类不支持多继承?
- 如果C类同时继承了A、B类,但是A、B类中都有同名方法时,C类在调用方法的时候是无法区分调用的是哪个类中的方法。
- 多层继承则不存在这个问题,假设C类继承A,D类继承C,如果A类和C类中都有同名方法,D类调用的时候只会选择C类中的方法,Java会采取就近原则。
object类
- object类是java中所有类的祖宗。我们写的任意类,其实都是object的子类或者子孙类。
方法重写
- 什么是方法重写?
- 当子类觉得父类中的某个方法不好用,或者无法满足自己的需求时,子类可以重写一个方法名称、参数列表一样的方法,去覆盖父类的这个方法,这就是重写。
- 注意:重写后,方法的访问,Java会遵循就近原则。
方法重写的其他注意事项
- 重写小技巧:使用Override注解,他可以指定java编译器,检查我们方法重写的格式是否正确,代码可读性也会更好。
- 子类重写父类方法时,访问权限必须大于或者等于父类该方法的权限(public > protected > 缺省)。
- 重写的方法返回值类型,必须与被重写方法的返回值类型一样,或者范围更小。
- 私有方法、静态方法不能被重写,如果重写会报错的。
案例:
父类:
public class Animal {
public void run(){
System.out.println("每个动物都会跑!");
}
}
子类:
public class Tiger extends Animal{
// 方法重写:名称相同,参数列表相同,返回值类型相同
@Override //重写的校验注解:安全,优雅
public void run(){
System.out.println("老虎跑的贼快!");
}
}
main方法:
public static void main(String[] args) {
Tiger t = new Tiger();
t.run();
}
输出结果:
老虎跑的贼快!
方法重写的应用场景
- 子类从写Object类的toString()方法,以便返回对象内容。
案例:
创建一个学生类:
public class Student {
private String name;
private char sex;
private double height;
private String desc;
public Student() {
}
public Student(String nanme, char sex, double height, String desc) {
this.name = nanme;
this.sex = sex;
this.height = height;
this.desc = desc;
}
public String getNanme() {
return name;
}
public void setNanme(String nanme) {
this.name = nanme;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
@Override
public String toString(){
return "Student {name = " + name + ", sex = " + sex + ", height = " + height + ", desc = " + desc + "}";
}
}
main方法:
// 目标:搞清楚方法重写在实际开发类中的应用场景。
public class Test {
public static void main(String[] args) {
Student s1 = new Student("王小二", '男', 1.78, "是个好学生");
System.out.println(s1);
}
}
输出结果:
Student {name = 王小二, sex = 男, height = 1.78, desc = 是个好学生}
在打印对象时,实际是调用了objcet类中的toString方法,输出的结果就是对象的内存地址。如果toString被重写后,在打印对象时,则调用的是重写后的toString方法。
子类中访问其他成员的特点
在子类方法中,访问其他成员(成员变量、成员方法),是依据就近原则。
- 先子类局部范围找。
- 然后子类成员范围找。
如果子父类中,出现了重名的成员,会优先使用子类的,如果此时一定要在子类中使用父类的成员怎么办?
- 可以通过super关键字,指定访问父类的成员:super.父类成员变量/父类成员方法
VS this:
- 代表的对象不同:
this:本身调用者的这个对象
super:代表父类对象的应用 - 调用前提:
this:没有继承也可以使用。
super:只能在继承后使用。 - 构造方法:
this(),调用的是本类的构造。
super(),调用的是父类中的构造。
案例:
// 目标:继承过后,子类访问成员的特点,就近原则
public class Test {
public static void main(String[] args) {
Zi z = new Zi();
z.showName();
}
}
class Zi extends Fu{
String name = "子类名称";
public void showName(){
String name = "局部名称";
System.out.println(name);
System.out.println(this.name);// 访问子类成员name
}
}
class Fu{
String name = "父类名称";
}
输出结果:
局部名称
子类名称
-------------------------------------------------------------
public class Test2 {
public static void main(String[] args) {
Zi2 z = new Zi2();
z.run();
z.go();
}
}
class Zi2 extends Fu2{
@Override
public void run(){
System.out.println("子类跑");
}
public void go(){
run(); // 调用子类的run方法
super.run();// 调用父类的run方法
}
}
class Fu2{
public void run(){
System.out.println("父类跑");
}
}
输出结果:
子类跑
子类跑
父类跑
子类构造器的特点
- 子类的全部构造器,都会先调用父类的构造器,再执行自己。
案例:
父类:
public class Animal {
public Animal(){
System.out.println("父类无参构造器");
}
public Animal(String n){
System.out.println("父类有参构造器");
}
}
子类:
public class Wolf extends Animal{
public Wolf() {
System.out.println("子类Wolf无参构造器");
}
public Wolf(String n){
System.out.println("子类Wolf有参构造器");
}
}
main方法:
//目标:搞清楚子类构造器的特点:子类全部构造器会优先调用父类的构造器,再执行子类的构造器
public class Test {
public static void main(String[] args) {
// 子类的全部构造器都会先调用父类的构造器,在执行子类的构造器
Wolf w = new Wolf();
Wolf w2 = new Wolf("wolf");
}
}
输出结果:
父类无参构造器
子类Wolf无参构造器
父类无参构造器
子类Wolf有参构造器
子类构造器是如何实现父类构造器的?
- 默认情况下,子类全部构造器的第一行代码都是super()(写不写都有),它会调用父类的无参构造器。
- 如果父类没有无参构造器,则我们必须在子类构造器的第一行手写super(……),指定去调用父类的有参构造器。
为什么子类的全部构造器会先调用父类的构造器?
案例:
// 父类
public class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
子类:
public class Teacher extends Person{
private String skill;
public Teacher() {
}
public Teacher(String name, int age, String skill) {
super(name,age); //子类调用父类构造器:初始化继承自父类的那部分数据
this.skill = skill;
}
public String getSkill() {
return skill;
}
public void setSkill(String skill) {
this.skill = skill;
}
}
main方法:
public static void main(String[] args) {
Teacher t1 = new Teacher();
Teacher t2 = new Teacher("蜘蛛侠", 30, "教语文");
t1.setName("钢铁侠");
t1.setAge(20);
t1.setSkill("教数学");
System.out.println(t1.getName());
System.out.println(t1.getAge());
System.out.println(t1.getSkill());
System.out.println(t2.getName());
System.out.println(t2.getAge());
System.out.println(t2.getSkill());
}
输出结果:
钢铁侠
20
教数学
蜘蛛侠
30
教语文
- 子类构造器可以通过父类构造器,把对象中包含父类这部分的数据先初始化赋值,再回来把对象利包含子类这部分的数据也进行初始化赋值。
这样既调用了父类的构造器又调用了子类的构造器,这样就保证了数据的完整性。
this(……)调用兄弟构造器
- 任意类的构造器中,是可以通过this(……)去调用该类的其他构造器的。
案例:
学生类:
public class Student {
private String name;
private int age;
private String school;
public Student() {
}
public Student(String name, int age){
this(name, age, "霍格沃兹");
}
public Student(String name, int age, String school) {
this.name = name;
this.age = age;
this.school = school;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSchool() {
return school;
}
public void setSchool(String school) {
this.school = school;
}
}
main方法:
public static void main(String[] args) {
// 1. 创建对象封装数据
Student s1 = new Student("孙悟空", 500, "斜月三星洞");
System.out.println(s1.getName());
System.out.println(s1.getAge());
System.out.println(s1.getSchool());
// 不需要给学校赋值,默认值是霍格沃兹
// 注意事项:this(...),super(...)不能同时出现,且必须在构造器的第一行。
Student s2 = new Student("蜘蛛精", 300);
System.out.println(s2.getName());
System.out.println(s2.getAge());
System.out.println(s2.getSchool());
}
输出结果:
孙悟空
500
斜月三星洞
蜘蛛精
300
霍格沃兹
- 注意事项:this(...),super(...)不能同时出现,且必须在构造器的第一行。
- 如果同时出现,this(...)会调用有参构造器,有参构造器会调用父类的有参构造器,这是如果在调用super(……)就会出现重复调用父类构造器的问题。
11Java基础之继承的更多相关文章
- 二十二. Python基础(22)--继承
二十二. Python基础(22)--继承 ● 知识框架 ● 继承关系中self的指向 当一个对象调用一个方法时,这个方法的self形参会指向这个对象 class A: def get(s ...
- 第二十八节:Java基础-进阶继承,抽象类,接口
前言 Java基础-进阶继承,抽象类,接口 进阶继承 class Stu { int age = 1; } class Stuo extends Stu { int agee = 2; } class ...
- 11java基础继承
一. 继承相关 18.实现如下类之间的继承关系,并编写Music类来测试这些类. package com.hry.test; public class Instrument { ...
- Java基础学习-- 继承 的简单总结
代码参考:Java基础学习小记--多态 为什么要引入继承? 还是做一个媒体库,里面可以放CD,可以放DVD.如果把CD和DVD做成两个没有联系的类的话,那么在管理这个媒体库的时候,要单独做一个添加CD ...
- 三、Java基础---------关于继承、构造函数、静态代码块执行顺序示例讲解
在上节博客中曾提到过类的继承,这篇文章主要是介绍类的继承.构造函数以及静态代码块的执行顺序. 首先接着分析在黑马基础测试中的一个关于继承的题目,题目描述如下: 声明类Person,包含2个成员变量:n ...
- JAVA与多线程开发(线程基础、继承Thread类来定义自己的线程、实现Runnable接口来解决单继承局限性、控制多线程程并发)
实现线程并发有两种方式:1)继承Thread类:2)实现Runnable接口. 线程基础 1)程序.进程.线程:并行.并发. 2)线程生命周期:创建状态(new一个线程对象).就绪状态(调用该对象的s ...
- 【Java基础】继承的一些总结
什么是继承 把一些类的具有共性的东西剥离出来形成一个新的类,然后各个其他类保留自己独有的特性,并用关键字extends继承这个剥离出来的新的类,可以最终达到各类原始相同效果,但是在每个类中,单用一个“ ...
- Java基础08 继承
作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 继承(inheritance)是面向对象的重要概念.继承是除组合(composit ...
- C++基础——类继承中方法重载
一.前言 在上一篇C++基础博文中讨论了C++最基本的代码重用特性——类继承,派生类可以在继承基类元素的同时,添加新的成员和方法.但是没有考虑一种情况:派生类继承下来的方法的实现细节并不一定适合派生类 ...
- Python基础之继承与派生
一.什么是继承: 继承是一种创建新的类的方式,新建的类可以继承一个或过个父类,原始类成为基类或超类,新建的类则称为派生类 或子类. 其中,继承又分为:单继承和多继承. class parent_cla ...
随机推荐
- 【语义分割专栏】先导篇:常用数据集(VOC、Camvid、Cityscape、ADE20k、COCO)
目录 前言 mask模式 PASCAL-VOC2012 下载 数据集简介 数据加载(dataloader) CamVid 下载 数据集简介 数据加载(dataloader) Cityscape 下载 ...
- c++并发编程实战-第3章 在线程间共享数据
线程间共享数据的问题 多线程之间共享数据,最大的问题便是数据竞争导致的异常问题.多个线程操作同一块资源,如果不做任何限制,那么一定会发生错误.例如: 1 int g_nResource = 0; 2 ...
- TVM:TensorIR
TensorIR是一种用于深度学习的特定领域语言,主要有两个目的. 在各种硬件后端进行程序变换和优化的实现 用于自动张量化程序优化的抽象 import tvm from tvm.script.pars ...
- manim 动画效果总结
ManimCE作为一个强大的动画制作框架,它为创作者提供了丰富多样的动画效果,无论是文字.图形还是其他元素,都能通过这些动画效果呈现出生动.有趣的视觉体验. 本文将详细总结ManimCE(v0.19. ...
- JuiceFS v1.3-Beta1:一亿文件备份分钟级完成,性能优化全解析
在最新发布的 JuiceFS v1.3 Beta1 版本中,我们引入了一种全新的二进制备份机制,旨在更高效地应对亿级文件规模下的备份与迁移场景.相比现有的 JSON 备份方式,该机制在导入导出元数据时 ...
- 第二次阶段性OOP题目集总结性Blog
前言: 基础题目训练说明 第一次基础题目有两道,题量较少,通过对之前题目的进一步扩展,考察知识点主要是1.类的封装.继承.多态2.抽象类3.接口.题目主要考查了学生对代码结构和可扩展性优化的能力.难度 ...
- K8s新手系列之DaemonSet资源
概述 官网文档:https://kubernetes.io/zh-cn/docs/concepts/workloads/controllers/daemonset/ DaemonSet简称ds Dae ...
- MySQL中以数值类型存储IP地址
前言 数据库中存储IP地址的时候,推荐使用整数存储而不是字符串.一般来说, 在保证正确性的前提下,尽量使用最小的数据类型来存储和展示数据:小的数据类型一般比大的更快,因为小的数据类型占用的磁盘空间 ...
- Jenkinsfile_定义全局全量
一.通过def定义全局变量 注意:首行def定义的变量不能使用=赋值. def var pipeline { agent any stages { stage("定义var") { ...
- 香港CN2优化线路带宽低延迟VPS服务器推荐
原文:https://ichochy.com/posts/20231120.html CN2 CN2,中国电信下一代承载网(ChinaNetNextCarryingNetwork).CN2是一个多业务 ...