多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那个类即可。
•通过extends关键字可以实现类与类的继承
•class 子类名 extends 父类名 {}
继承的好处
•提高了代码的复用性
•多个类相同的成员可以放到同一个类中
•提高了代码的维护性
•如果功能的代码需要修改,修改一处即可
•让类与类之间产生了关系,是多态的前提
•其实这也是继承的一个弊端:类的耦合性很强
3)注意事项:
Java只支持单继承
子类只能继承父类所有非私有的成员(成员方法和成员变量)
•其实这也体现了继承的另一个弊端:打破了封装性
子类不能继承父类的构造方法,但是可以通过super(后面讲)关键字去访问父类构造方法。
不要为了部分功能而去继承
我们到底在什么时候使用继承呢?
•继承中类之间体现的是:”is a”的关系。
4)继承中成员变量的关系
•在子类方法中访问一个变量
•首先在子类局部范围找
•然后在子类成员范围找
•最后在父类成员范围找(肯定不能访问到父类局部范围)
•如果还是没有就报错。(不考虑父亲的父亲…)
5)super和this的用法
•super代表父类存储空间的标识(可以理解为父类引用)
用法(this和super均可如下使用)
访问成员变量
this.成员变量 super.成员变量
访问构造方法(子父类的构造方法问题讲)
this(…) super(…)
访问成员方法(子父类的成员方法问题讲)
this.成员方法() super.成员方法()
6)继承中构造方法的关系
子类中所有的构造方法默认都会访问父类中空参数的构造方法
为什么呢?
•因为子类会继承父类中的数据,可能还会使用父类的数据。所以,子类初始化之前,一定要先完成父类数据的初始化。
•每一个构造方法的第一条语句默认都是:super()
如何父类中没有构造方法,该怎么办呢?
•子类通过super去显示调用父类其他的带参的构造方法
•子类通过this去调用本类的其他构造方法
•本类其他构造也必须首先访问了父类构造
•一定要注意:
•super(…)或者this(….)必须出现在第一条语句位置上
•否则,就会有父类数据的多次初始化
6)继承中成员方法的关系
方法重写概述
•子类中出现了和父类中一模一样的方法声明,也被称为方法覆盖,方法复写。
•使用特点:
•如果方法名不同,就调用对应的方法
•如果方法名相同,最终使用的是子类自己的
方法重写的注意事项
•父类中私有方法不能被重写
•子类重写父类方法时,访问权限不能更低
•父类静态方法,子类也必须通过静态方法进行重写。(其实这个算不上方法重写,但是现象确实如此,至于为什么算不上方法重写,多态中我会讲解)
是最终的意思,可以修饰类,成员变量,成员方法。
•修饰类,类不能被继承
•修饰变量,变量就变成了常量,只能被赋值一次
•修饰方法,方法不能被重写
1)final修饰局部变量
•在方法内部,该变量不可以被改变
•在方法声明上,分别演示基本类型和引用类型作为参数的情况
•基本类型,是值不能被改变
•引用类型,是地址值不能被改变
2)final初始化的时机
在对象构造完毕前即可。
•某一个事物,在不同时刻表现出来的不同状态。
1)多态的前提和体现
•有继承关系
•有方法重写
•有父类引用指向子类对象
2)成员访问特点
成员变量
编译看左边,运行看左边
成员方法
编译看左边,运行看右边
静态方法
编译看左边,运行看左边
所以前面我说静态方法不能算方法的重写
3)多态的好处和弊端
多态的好处
•提高了程序的维护性(由继承保证)
•提高了程序的扩展性(由多态保证)
多态的弊端
•不能访问子类特有功能
•那么我们如何才能访问子类的特有功能呢?
•多态中的转型
4)多态中的转型问题
向上转型
•从子到父
•父类引用指向子类对象
向下转型
•从父到子
•父类引用转为子类对象
④抽象类:现实生活中有一些定义其实是没有具体指向的,如动物。表达的是一些共同特征的集合,没有实例化的意义。
1)抽象类的特点
•抽象类和抽象方法必须用abstract关键字修饰
•格式
•abstract class 类名 {}
•public abstract void eat();
•抽象类不一定有抽象方法,有抽象方法的类一定是抽象类
•抽象类不能实例化
子类要么是抽象类,要么就必须实现其中所有的抽象方法。
2)抽象类的成员特点 ------->和普通的类进行比较,类用abstract修饰,类中可以定义abstract方法,不能实例化
成员变量
•可以是变量
•也可以是常量
构造方法
•有构造方法,但是不能实例化
•那么,构造方法的作用是什么呢?
•用于子类访问父类数据的初始化
成员方法
•可以有抽象方法 限定子类必须完成某些动作
•也可以有非抽象方法 提高代码服用性
3)抽象类和那些关键字冲突
•private 冲突
•final 冲突
•static 无意义
⑤接口: 特殊的功能,例如火影中的血继限界,抽象表达的是公共模板而接口针对的是扩展。
1)接口的特点
•接口用关键字interface表示
•格式:interface 接口名 {}
•类实现接口用implements表示
•格式:class 类名 implements 接口名 {}
•接口不能实例化
•那么,接口如何实例化呢?
•按照多态的方式,由具体的子类实例化。其实这也是多态的一种,接口多态。
•接口的子类
•要么是抽象类
•要么重写接口中的所有抽象方法
2)接口成员特点
成员变量
•只能是常量
•默认修饰符 public static final
构造方法
•没有,因为接口主要是扩展功能的,而没有具体存在
成员方法
•只能是抽象方法
•默认修饰符 public abstract
抽象类和接口的区别
成员区别
•抽象类 变量,常量;有抽象方法;抽象方法,非抽象方法
•接口 常量;抽象方法
关系区别
•类与类 继承,单继承
•类与接口 实现,单实现,多实现
•接口与接口 继承,单继承,多继承
设计理念区别
•抽象类 被继承体现的是:”is a”的关系。共性功能
•接口 被实现体现的是:”like a”的关系。扩展功能
•其实就是文件夹 ,对类进行分类管理
1)语法:package com.pb.test;
2)注意事项
•package语句必须是程序的第一条可执行的代码
•package语句在一个java文件中只能有一个
•如果没有package,默认表示无包名
3)带包的java文件的编译和运行
手动式
•a:javac编译当前类文件。
•b:手动建立包对应的文件夹。
•c:把a步骤的class文件放到b步骤的最终文件夹下。
•d:通过java命令执行。注意了:需要带包名称的执行
•java cn.itcast.HelloWorld
自动式
•a:javac编译的时候带上-d即可
•javac -d . HelloWorld.java
•b:通过java命令执行。和手动式一样
•import 包名;
⑦权限修饰符
1)类及其成员可以使用的修饰符
类:
•默认,public,final,abstract
•我们自己定义:public居多
成员变量:
•四种权限修饰符均可,final,static
•我们自己定义:private居多
构造方法:
•四种权限修饰符均可,其他不可
•我们自己定义:public 居多
成员方法:
•四种权限修饰符均可,fianl,static,abstract
•我们自己定义:public居多
⑧内部类:l把类定义在其他类的内部,这个类就被称为内部类。
1)内部类的访问特点
•内部类可以直接访问外部类的成员,包括私有。
•外部类要访问内部类的成员,必须创建对象。
2)内部类的分类,由位置来进行划分
成员位置(成员内部类)
局部位置(局部内部类)
|-成员内部类:
l外部类名.内部类名 对象名 = 外部类对象.内部类对象;
注:一般来说,在实际开发中是不会这样使用的。因为一般内部类就是不让外界直接访问的。如电脑的CPU
成员内部的常见修饰符
•private 为了保证数据的安全性
•static 为了让数据访问更方便
•被静态修饰的成员内部类只能访问外部类的静态成员
面试题:num this.num Outer.this.num
|-局部内部类
可以直接访问外部类的成员
可以创建内部类对象,通过对象调用内部类方法,来使用局部内部类功能
局部内部类访问局部变量的注意事项:
•必须被final修饰?
•为什么呢?
因为局部变量会随着方法的调用完毕而消失,这个时候,局部对象并没有立马从堆内存中消失,还要使用那个变量。为了
让数据还能继续被使用,就用fianl修饰,这样,在堆内存里面存储的其实是一个常量值。通过反编译工具可以看一下
|-匿名内部类,使用场景:参数是抽象类或接口的情况。
就是内部类的简化写法,这里的类可以是具体类也可以是抽象类。
前提:存在一个类或者接口
格式:
new 类名或者接口名() {重写方法;}
本质:
•是一个继承了类或者实现了接口的子类匿名对象