当某个属性是所有对象共享
的,这种情况下一般使用static来修饰
static表示静态,是Java中的一个修饰符,可以修饰成员方法,成员变量
被static修饰的成员变量,叫做静态变量
调用方式:
类名
调用(推荐)
对象名
调用
static内存图
说明:
静态区
是存储静态的位置堆中
特点:
被该类所有对象共享
不属于对象, 属于类
随着类的加载而加载,优先于对象存在
被static修饰的成员方法,叫做静态方法
特点:
测试类和工具类
中调用方式:
类名
调用(推荐)对象名
调用Javabean类:用来描述一类事务的类
测试类:用来检查其他类是否书写正确,带有main方法,是程序的入口
工具类:不是用来描述一类事务的,而是帮我们做一些事情的类
定义工具类需要遵守的规则:
见名知意
私有化
构造方法静态
私有化构造方法的原因:工具类不是用来描述一类事务的类,所以创建它的对象无意义
说明:
this表示所在方法的调用者的地址值
在非静态方法中,在形参的最前面,有一个隐藏的this,这个this的值是由虚拟机赋值的
由于在方法内没有与成员变量重名的局部变量,所以this是隐藏的
当局部变量与成员变量重名时,隐藏的this就失效了,根据就近原则访问的是局部变量,但
此时就想访问成员变量,需要把this关键字显示的写出来就可以了
由于静态方法是共享的,不会单独与某个对象有联系,所以静态方法中没有this关键字
静态随着类的加载而加载
非静态跟对象有关
由于非静态数据是在对象创建之后出现在内存当中的
而静态数据是随着类的加载而加载到内存当中的,而如果此时没有创建对象,则非静态数据没有在内存中
所以静态数据无法访问非静态数据
重新认识main方法
public:被JVM调用,访问权限足够大
static:被JVM调用,不用创建对象,直接类名访问
因为main方法是静态的,所以测试类中其他方法也是静态的
void:被JVM调用,不需要给JVM返回值
main:一个通用的名称,虽然不是关键字,但是被JVM识别
String[] args:以前用于接收键盘录入数据的,现在没用
什么是继承?
继承是面向对象三大特征之一,可以让类跟类之间产生子父关系
面向对象三大特征
由于多个类的内容有重复的地方,所以可以把重复的内容抽取出来放在一个类中,让其他类去继承这个类
继承的格式:
使用继承的好处:
提高代码的复用性
使子类更强大
得到
父类的属性和行为,子类可以使用学习的重点:自己设计继承结构体系
什么时候用继承?
当类与类之间存在相同的内容
,并满足子类是父类中的一种
,就可以考虑使用继承来优化代码
Java只支持单继承,不支持多继承,但支持多层继承
单继承:一个子类只能继承一个父类
不支持多继承:子类不能同时继承多个父类
多层继承:子类A继承父类B,父类B可以继承父类C
每一个类都直接或者间接的继承于Object
如果我们定义一个类,没有为其设计继承关系
A会默认继承Object类
extends Object是由虚拟机自动的加上去的
当我们写的Javabean类越来越多的时候,就会形成继承体系
在继承体系当中,针对于任何一个子类,可以使用自己直接或者间接父类中的内容
子类只能访问父类中非私有的成员
父类中有什么?
继承下来和调用不是一个概念
构造方法是否可以被继承
不能被子类继承,因为违背了构造方法的定义规则,方法名和子类名不一致
成员变量是否可以被继承
不管是私有的,还是非私有的成员变量,子类都可以继承下来,但子类只能访问非私有的,如果想要访问私有的需要使用get()/set()
成员方法是否可以被继承
首先有一个继承结构
现在有一段这样的代码
其中的对象a调用方法c(),那么是怎么调用的呢?
Java在最顶层的父类
开始,设立一个虚方法表,会把虚方法放到虚方法表当中
虚方法:
过程如下:
只有父类中的虚方法才能被子类继承
当子类调用show2()时,子类会先到自己的虚方法表
中去找show2(),子类在虚方法表中没有找到,则会到自己类中去找,也没有找到
,依次到父类中去找,在父类中找到了show2(),发现show2()是私有的,所以z.show2()就会报错
就近原则:谁离我近,我就用谁
如果出现了重名的成员变量
直接调用满足就近原则:谁离我近,我就用谁
super调用:直接访问父类
方法的重写
应用场景:当父类的方法不能满足子类现在的需求时,需要进行方法重写
书写格式:
在继承体系中,子类出现了和父类中一模一样的方法声明,我们就称子类这个方法是重写的方法
@Override重写注解
本质:
方法重写的注意事项和要求
方法重写的建议:重写方法的声明尽量和父类保持一致
父类中的构造方法不会被子类继承
子类中所有的构造方法默认先访问父类中的无参构造,再执行自己
原因:
子类在初始化的时候,有可能会使用到父类中的数据,如果父类没有完成初始化,子类将无法使用父类的数据
所以,子类初始化之前,一定要调用父类构造方法先完成父类数据空间的初始化
怎么调用父类构造方法的?
子类构造方法的第一行语句默认都是:super(),不写也存在,且必须在第一行
如果想调用父类有参构造,必须手动写super进行调用
this:理解为一个变量,表示当前方法调用者的地址值
super:代表父类存储空间
什么是多态?
面向对象三大特征
多态,就是同类型的对象表现出的不同形态
比如,我们设计两个类,一个是学生类,一个是教师类,让这两个类去继承表示人的类
上面那种情况学生对象此时是学生形态
下面这种情况学生对象此时是人的形态
多态的应用场景
假设有一个学生管理系统,现有三种不同的角色分别是:学生,教师,管理员
任何一个角色去登录系统的时候,都要提前去注册
那么注册方法,就需要相应角色的对象
那么此时的需求是,用一个通用类型去接收不同角色的对象
这种情况就需要用到多态
多态的表现形式
父类类型 对象名称 = 子类对象;
多态的前提
多态的好处
使用父类型作为参数,可以接收所有子类对象,体现多态的扩展性与便利
变量调用:编译看左边,运行看左边
方法调用:编译看左边,运行看右边
多态调用成员的内存图解
多态的优势
在多态形式下,右边对象可以实现解耦合便于扩展和维护
比如,
此时是学生工作,若以后想要实现教师工资,只需要将new Student()改为new Teacher()即可
定义方法的时候,使用父类型作为参数,可以接收所有子类对象,体现多态的扩展性与便利
多态的弊端
不能调用子类特有功能
解决方案:
变回子类型就可以了
比如,Dog dog = (Dog)a;
细节,转换的时候不能瞎转,如果转成其他类的类型,就会报错
引用数据类型的类型转换的方式
自动类型转换
强制类型转换
强制类型转换能解决什么问题?
什么是包?
包就是文件夹,用来管理各种不同功能的Java类,方便后期代码维护
包名的规则
公司域名反写+包的作用,需要全部英文小写,见名知意
例如:www.itheima.com -> com.itheima.domain
包名.类名->全类名
使用其他类的规则
最终的->不能被改变的
可以修饰:
常量
实际开发中,常量一般作为系统的配置信息,方便维护,提高可读性
常量的命名规范:
细节:
核心:常量记录的数据是不能发生改变的
修饰符的分类:
范围由小到大:private<默认 使用规则: 实际开发中,一般只用private和public 局部代码块:写在方法内的代码块 作用:提前结束变量的生命周期,节约内存空间 构造代码块:写在成员位置的代码块 作用: 当两个构造方法中具有相同的代码内容时 比如, 此时,使用构造代码块,写在成员位置 静态代码块 格式:static{} 特点:需要通过static关键字修饰,随着类的加载而加载,并且自动触发,只执行一次 使用场景:在类加载的时候,做一些数据初始化的时候使用 将共性的行为抽取到父类后,由于每一个子类执行的内容是不一样的 所以,在父类中不能确定具体的方法体,该方法就可以定义为抽象方法 定义格式 public abstract 返回值类型 方法名(参数列表); 如果一个类中存在抽象方法,那么该类就必须声明为抽象类 定义格式 public abstract class 类名{} 注意事项 强制让子类按照某种格式重写 在公司当中,一个项目是由很多人来完成的,如果不将相同的行为抽取到父类中,那么在实际开发中会很麻烦 就如下图所示 在调用狗的吃方法就要到狗类中去看方法的声明特点,调用猫的吃方法就要到猫类中去看方法的声明特点,很麻烦 如果将相同的行为抽取到父类中,只需到父类这一个地方看吃方法就可以了 父类中的内容是所有子类的共性内容 但是如果有部分子类的共享内容是不可以放到父类中的 这个时候,就可以把部分子类的共享内容放到接口中(如果是一个子类,就不需要接口了) 所以说,接口就是一种规则 接口代表规则,是行为的抽象 想要让哪个类拥有哪个行为,就让这个类实现对应的接口就可以了 抽象类一般用在父类当中,抽取子类共性内容后,方法体不确定,将该方法定义为抽象方法,抽象方法所在的类就是抽象类,表示一类事务 接口不是表示一类事务的,接口侧重于行为,只要行为相同就可以抽取到接口中 又因为接口中的行为是抽象方法, 所以,接口就是一种规则,是对行为的抽象 接口用关键字interface来定义 public interface 接口名{} 接口不能实例化 接口和类之间是实现关系,通过implements关键字表示 public class 类名 implements 接口名{} 接口的子类(实现类) 注意: 接口和类是实现关系,可以单实现,也可以多实现 public class 类名 implements 接口名1,接口名2{} 实现类还可以在继承一个类的同时实现多个接口 public class 类名 extends 父类 implements 接口名1,接口名2{} 成员变量 只能是常量 默认修饰符:public static final 构造方法 没有 成员方法 只能是抽象方法 默认修饰符:public abstract jdk7以前:接口中只能定义抽象方法 jdk8的新特性:接口中可以定义有方法体的方法 jdk9的新特性:接口中可以定义私有方法 类和类的关系 继承关系,只能单继承,不能多继承,但是可以多层继承 类和接口的关系 实现关系,可以单实现,也可以多实现,还可以继承一个类的同时实现多个接口 接口和接口的关系 继承关系,可以单继承,也可以多继承 细节:如果实现类实现了最下面的子接口,那么就需要重写所有的抽象方法 允许在接口中定义默认方法,需要使用关键字default修饰 作用:解决接口升级的问题 接口中默认方法的定义格式: 接口中默认方法的注意事项 允许在接口中定义静态方法,需要用static修饰 接口中静态方法的定义格式: 接口中静态方法的注意事项 当接口中的两个默认方法里面有相同的代码的时候,可以将相同的部分单独抽取出来放到另一个方法中 如下图, 但是,由于log()是为接口中其他方法提供服务的,所以不想被实现类使用,因为没意义,所以 接口中私有方法的定义格式 格式一:private 返回值类型 方法名(参数列表){} 例如:private void show() 格式二:private static 返回值类型 方法名(参数列表){} 例如:private static void show(){} 私有方法分为两种 设计模式是一套被反复使用,多人知晓的,经过分类编目的,代码设计经验的总结 使用设计模式是为了可重用代码,让代码更容易被他人理解,保证代码可靠性,程序的重用性 简单理解:设计模式就是各种套路 总结: 类的五大成员 属性、方法、构造方法、代码块、内部类 什么是内部类? 在一个类的里面,再定义一个类 例如:在A类的内部定义B类,B类就被称为内部类 为什么学习内部类? 举个例子 除了发动机的品牌,其余属性都是汽车的 所以把发动机的品牌也放到汽车类的成员位置就不合适了 需要设计发动机的类,把发动机的品牌放到发动机类的成员位置 又因为,发动机的品牌 属于汽车的 所以,把发动机的类写在汽车的成员位置 定义内部类要遵守的规则 内部类的访问特点 内部类的分类 成员内部类如何书写 获取成员内部类对象的方式 方式一: 在外部类中编写方法,对外提供内部类的对象 方式二: 直接创建格式:外部类名.内部类名 对象名 = 外部类对象.内部类对象; 内部类的内存图 静态内部类是成员内部类的一种特殊情况,就是在原来成员内部类的基础上加上static关键字 静态内部类只能访问外部类中的静态变量和静态方法,如果想要访问非静态的需要创建外部类的对象 创建静态内部类对象的格式: 外部类名.内部类名 对象名 = new 外部类名.内部类名(); 调用非静态方法的格式: 先创建对象,用对象调用 调用静态方法的格式: 外部类名.内部类名.方法名() 将内部类定义在方法里面就叫做局部内部类,类似于方法里面的局部变量 外界是无法直接使用局部内部类的,需要在方法内部创建对象并使用 局部内部类和局部变量是类似的,局部变量是不能直接被外界使用的 所以,局部内部类是不能被外界直接使用的 在局部内部类所在方法里,创建局部内部类的对象,用该对象访问局部内部类里面的内容 该类可以直接访问外部类成员,也可以访问方法内的局部变量 匿名内部类本质上就是隐藏了名字的内部类,可以写在成员位置,也可以写在局部位置 格式: new 类名或者接口名(){ 重写方法; }; 整体的格式包含了三部分: 例如: new Inter(){ public void show(){} }; 整体就是一个类的子类对象或者一个接口的实现类对象 使用场景: 当方法的参数是接口或者类时, 以接口为例,可以传递这个接口的实现类对象, 如果实现类只需要使用一次,就可以用匿名内部类简化代码
4.代码块
五.抽象类和抽象方法
1.抽象方法
2.抽象类
3.抽象类和抽象方法的意义
六.接口
1.为什么有接口?
2.接口的应用
3.接口和抽象类的异同
4.接口的定义和使用
5.接口中成员的特点
6.接口和类之间的关系
7.JDK8以后接口中新增的方法
8.JDK9新增的方法
9.适配器设计模式
七.内部类
1.成员内部类
2.静态内部类
3.局部内部类
4.匿名内部类