Java入门系列-16-继承
这一篇文章教给新手学会使用继承,及理解继承的概念。掌握访问修饰符、掌握 final 关键字的用法。
继承
为什么要使用继承
首先我们先看一下这两个类:
public class Teacher {
private int teachingAge;
private String name;
private int age;
public void teach() {
}
public void seyHi() {
System.out.println("我是:"+this.name);
}
}
public class Student {
private int studentNo;
private String name;
private int age;
public void learn() {
}
public void seyHi() {
System.out.println("我是:"+this.name);
}
}
Student 类和 Teacher 类中有一些相同的属性和方法,这些都属于重复代码,当一个程序中有大量的类时,就会产生大量的重复代码。这些重复的代码能不能抽取出来然后供其他类使用以简化呢,那就是使用继承。
使用继承优化之后:
创建 inherit 包
父类:(公共代码类)
package inherit;
public class People {
private String name;
private int age;
public void sayHi() {
System.out.println("我是:"+this.name);
}
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;
}
}
子类:Student.java
package inherit;
public class Student extends People{
private int studentNo;
public void learn() {
System.out.println("学习课程");
}
public int getStudentNo() {
return studentNo;
}
public void setStudentNo(int studentNo) {
this.studentNo = studentNo;
}
}
子类:Teacher.java
package inherit;
public class Teacher extends People{
private int teachingAge;
public void teach() {
System.out.println("教授课程");
}
public int getTeachingAge() {
return teachingAge;
}
public void setTeachingAge(int teachingAge) {
this.teachingAge = teachingAge;
}
}
测试类:
package inherit;
public class TestInherit {
public static void main(String[] args) {
//创建Student对象
Student stu=new Student();
stu.setName("张三");//父类中继承过来的方法
stu.learn();//子类中特有的方法
stu.sayHi();
//创建Teacher对象
Teacher teacher=new Teacher();
teacher.setName("汤尼");
teacher.setTeachingAge(2);//子类中特有的方法
teacher.sayHi();
}
}
观察上面示例代码我们发现:
1.子类的公共代码都可以放在父类中
2.子类可以有自己独有的方法和属性
3.子类一旦继承父类就会拥有父类的属性和方法
4.将公共代码放入父类,更方便统一修改代码
继承的语法
关键字:extends
1.编写父类
public class 父类{
//公共的属性和方法
}
2.编写子类,继承父类
public class 子类 extends 父类{
//子类特有的属性和方法
}
子类只能继承一个父类
子类访问父类成员
子类要想访问父类的成员要使用 super
关键字,super
代表父类对象
访问父类构造方法:
super();//访问无参构造
super(参数);//访问有参构造
访问父类属性:
super.name;
访问父类方法:
super.print();
访问父类构造,必须在子类构造方法中调用,必须是第一句
super 只能出现在子类的方法和构造方法中
super 不能访问父类的 private 成员
敲一敲:访问父类成员
创建包 visitparent 后在报下创建如下类
父类
package visitparent;
public class Animal {
private String name;
private int legs;
public Animal() {
this.name="无名";
this.legs=4;
}
public Animal(String name,int legs) {
this.name=name;
this.legs=legs;
}
public void eat(String food) {
System.out.println(name+" 吃食物:"+food);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getLegs() {
return legs;
}
public void setLegs(int legs) {
this.legs = legs;
}
}
子类
package visitparent;
public class Cat extends Animal{
private String hairColor;//毛发颜色
private int age;
public Cat () {
super();//调用父类无参
}
public Cat(String name,int legs,String hairColor,int age) {
super(name, legs);//这里调用相当于重用父类构造方法了
this.hairColor=hairColor;
this.age=age;
//super(name, legs);//去掉注释试试
//this.name="无名";//去掉注释试试
}
public void catchMouse() {
System.out.println(super.getName()+":抓老鼠");
}
public void paly() {
System.out.println(super.getName()+" 玩累了。");
super.eat("小鱼干");
}
public String getHairColor() {
return hairColor;
}
public void setHairColor(String hairColor) {
this.hairColor = hairColor;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
子类不能继承父类的 private 成员
子类不能继承不同包使用默认访问权限的成员(默认访问权限就是不写访问修饰符)
子类不能继承父类的构造方法
多重继承的执行流程
在创建子类的时候父类在做什么?
下面创建3个类观察执行流程,C类继承B类,B类继承A类。
A.java
public class A {
public A() {
System.out.println("A类的无参构造函数执行");
}
}
B.java
public class B extends A{
public B() {
System.out.println("B类的无参构造函数执行");
}
}
C.java
public class C extends B{
public C() {
System.out.println("C类的无参构造函数执行");
}
}
TestRunFlow.java 测试类,展示运行结果
public class TestRunFlow {
public static void main(String[] args) {
C c=new C();
}
}
运行结果为:
A类的无参构造函数执行
B类的无参构造函数执行
C类的无参构造函数执行
如果子类构造方法通过 super 显式调用父类相应构造方法,则不执行父类无参构造方法
子类构造方法默认会调用父类无参构造方法
调用父类无参构造方法,一直到执行顶级父类Object类的的无参构造方法为止
根据以上规则,判断下面的代码是否能编译通过
父类
public class Pet {
private String name;
public Pet(String name) {
this.name=name;
}
}
子类
public class Dog extends Pet{
}
答案是不能,父类中只有有参构造方法没有无参构造方法,子类中没有任何代码默认有一个隐式无参构造方法,子类无参构造方法默认调用父类无参构造方法,然而父类中没有,所有在子类中报错。
解决办法:1.在父类中显式添加无参构造方法,2.在子类构造方法中显式调用父类有参构造方法。
java 中的访问修饰符
访问修饰符 protected 能修饰属性和方法,修饰后本类、子类、同包可以访问。
访问修饰符 | 本类 | 同包 | 子类 | 其他 |
---|---|---|---|---|
private | √ | |||
默认(friendly) | √ | √ | ||
protected | √ | √ | √ | |
public | √ | √ | √ | √ |
方法重写
在"继承优化后"的代码中,Teacher 继承了 People 类,(忘记代码可以翻回去再看一遍) People 类中有个一个打招呼的方法 sayHi()
用于输出人的名字,但是 Teacher 调用这个方法并不能打印出 Teacher 的属性 teachingAge
的值,但是我们还想用这个方法实现这个功能,应该怎么办呢?
我们可以使用 方法重写 解决这个问题,修改子类 Teacher 中的代码,下面看一下使用方法重写后的效果。
Teacher.java
package inherit;
public class Teacher extends People{
//省略其他属性
@Override
public void sayHi() {
System.out.println("我是:"+super.getName()+" ,从事教育行业 "+this.teachingAge+" 年了。");
}
//省略其他方法、getter、setter
}
在 Eclipse 中重写某方法的快捷键是 Alt+Shift+S+V ,按完后选择要重写的方法
在 Idea 中重写某方法的快捷键是 Ctrl+O ,按完后选择要重写的方法
@Override 注解的作用, 用来检测是否符合重写规则,不符合重写规则将报错,这个注解可以不写
构造方法不能重写,因为构造方法不能被继承
方法重写的规则:
1.方法名相同
2.参数列表相同
3.返回值类型相同或者是其子类
4.访问权限不能严于父类
final 关键字的使用
1.final 修饰变量后变为常量
private static final long serialVersionUID = -6849794470754667710L;
2.final 修饰类后,该类不能被继承
package java.lang;
public final class Math {
//省略属性和方法……
}
3.final 修饰方法后,该方法不能被重写
public final void teach() {
System.out.println("教授课程");
}
4.final 修饰创建的对象后,该对像不能再次实例化(可以修改属性)
final Teacher teacher=new Teacher();
teacher.setName("汤尼");
//teacher=new Teacher();//去掉注释试试
String 类就是一个典型的被 final 修饰的类
搜索关注公众号「享智同行」,第一时间获取技术干货
Java入门系列-16-继承的更多相关文章
- Java入门系列之类继承、抽象类、接口(五)
前言 C#和Java关于类.抽象类.接口使用方式基本相似,只是对应关键字使用不同罢了,本节呢,我们只是对照C#和Java中关于这三个概念在具体使用时,看看有哪些不一样的地方. 类继承 C#和Java在 ...
- Java 集合系列 16 HashSet
java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...
- Java入门系列(三)面向对象三大特性之封装、继承、多态
面向对象综述 封装 封装的意义,在于明确标识出允许外部使用的所有成员函数和数据项,或者叫接口. 有了封装,就可以明确区分内外,使得类实现者可以修改封装内的东西而不影响外部调用者:而外部调用者也可以知道 ...
- Java入门系列-26-JDBC
认识 JDBC JDBC (Java DataBase Connectivity) 是 Java 数据库连接技术的简称,用于连接常用数据库. Sun 公司提供了 JDBC API ,供程序员调用接口和 ...
- java io系列16之 PrintStream(打印输出流)详解
本章介绍PrintStream以及 它与DataOutputStream的区别.我们先对PrintStream有个大致认识,然后再深入学习它的源码,最后通过示例加深对它的了解. 转载请注明出处:htt ...
- Java入门系列-18-抽象类和接口
抽象类 在第16节继承中,有父类 People People people=new People(); people.sayHi(); 实例化People是没有意义的,因为"人"是 ...
- Java入门系列(四)内部类
为什么需要内部类? 真正的原因是这样的,java中的内部类和接口加在一起,可以的解决常被C++程序员抱怨java中存在的一个问题没有多继承.实际上,C++的多继承设计起来很复杂,而java通过内部类加 ...
- Java入门系列-19-泛型集合
集合 如何存储每天的新闻信息?每天的新闻总数是不固定的,太少浪费空间,太多空间不足. 如果并不知道程序运行时会需要多少对象,或者需要更复杂方式存储对象,可以使用Java集合框架. Java 集合框架提 ...
- Java基础系列 - 抽象类继承和接口实现
package com.inter; /** * 继承和接口的关系,单继承,多接口 * java不支持多继承,但可通过接口实现多重继承 */ public class test2 { public s ...
- Java入门 - 面向对象 - 01.继承
原文地址:http://www.work100.net/training/java-inheritance.html 更多教程:光束云 - 免费课程 继承 序号 文内章节 视频 1 概述 2 继承的特 ...
随机推荐
- Djangorestframework编写post接口
前提:已经有Django环境 一.安装 pip install djangorestframework 二.编写视图 import json from django.shortcuts import ...
- .net 抽象类(abstract)和接口(interface)区别
1.抽象类 (1) 抽象方法只作声明,而不包含实现,可以看成是没有实现体的虚方法 (2) 抽象类不能被实例化 (3) 抽象类可以但不是必须有抽象属性和抽象方法,但是一旦有了抽象方法, ...
- PHP如何根据数组中的键值进行排序
主要是使用PHP的排序函数,asort()和arsort(). 为了减少代码的耦合性,我们将根据数组中的键值进行排序封装成一个函数 <?php $array = array( array(), ...
- JMeter—监听器
用来显示JMeter取样器的测试结果,能够以树.表.图形形式显示,也可以以文件方式保存. 一.设置默认配置 初始化配置文件设置: 监听器默认保存哪些数据域,可以在jmeter.properties(或 ...
- >>> 主页链接
服 务 & SDK 网易云信|真正稳定的IM即时通讯云服务 微信小程序开发工具下载 百度LBS开放平台 ( 百度地图API示例) 微信JSSDK说明文档 (在线demo) 园 友 京东开涛 W ...
- dbproxy-user/pwd
dbproxy 的账号是统一的, 即连接dbproxy,连接主mysql ,连接从mysql 的账号必须一样, 为了隔离 即使用dbproxy的人感知不到mysql, 需要分离 配置文件 #dbpro ...
- P1642 规划 01分数规划+树形DP
$ \color{#0066ff}{ 题目描述 }$ 某地方有N个工厂,有N-1条路连接它们,且它们两两都可达.每个工厂都有一个产量值和一个污染值.现在工厂要进行规划,拆除其中的M个工厂,使得剩下的工 ...
- P4383 [八省联考2018]林克卡特树lct 树形DP+凸优化/带权二分
$ \color{#0066ff}{ 题目描述 }$ 小L 最近沉迷于塞尔达传说:荒野之息(The Legend of Zelda: Breath of The Wild)无法自拔,他尤其喜欢游戏中的 ...
- Maven依赖的JAR包下载慢?赶紧看过来
相信许多JAVA开发者在日常工作中时常会碰到这种情况,那就是编译Maven工程时,工程所依赖的jar包文件下载非常慢,甚至经常出现下载不成功的问题,今天,小编就给大家讲讲如何提升Maven依赖包的下载 ...
- webpack中设置jquery为全局对象
通过npm安装jquery npm install jquery -D 然后配置webpack-config.js plugins: [ new webpack.ProvidePlugin({ $: ...