面向对象进阶
文章目录
- 面向对象进阶
- static关键字
- 继承
- 多态
- 包
- final
- 抽象类与抽象方法
- 接口
- 拓展
- 内部类
- 成员内部类
- 静态内部类
- 局部内部类
- 匿名内部类
static关键字
static表示静态,是Java中的一个修饰符,可以修饰成员方法,成员变量
静态变量是随着类的加载而加载的,优先于对象的创建
在堆内存中会开辟一块静态区,用来存储静态变量
被static修饰idea成员变量,叫做静态变量
特点:被该类所有的对象共享
不属于对象,属于类
随着类的加载而加载,优先于对象存在
调用方式:类名调用(推荐)
对姓名调用
内存图:
被static修饰的成员方法,叫做静态方法
特点:多用在测试类和工具类中
JavaBean类中很少会用
调用方法:类名调用(推荐)
对姓名调用
☆工具类:
帮助我们做一些事情,但是不描述任何事物的类
规范:类名见名知意
私有化构造方法(禁止创建该类的实例化对象)
方法定义为静态(方便调用)
注意事项
静态方法只能访问静态变量和静态方法
非静态方法可以访问静态变量或者静态方法,也可以访问非静态的成员变量和非静态的成员方法
静态方法中没有this关键字
总结: 静态方法中,只能访问静态(混圈子)
非静方法可以访问所有
静态方法中没有this关键字
内存图:
继承
类的无法成员:属性,方法,构造方法,代码块,内部类
封装
对象代表什么,就得封装对应的数据,并提供数据对应的行为
extends
Java中提供一个关键字extends,用这个关键字,我们可以让一个类和另一个类建立起继承关系
使用场景:当类与类之间,存在相同(共性) 的内容,并满足子类是父类的一种,就可以考虑使用继承,来优化代码
public class Student extends Person{}
Student 称为子类(派生类),Person成为父类(基类或者超类)
优点:可以把多个子类中重复的代码抽取到父类中,提高代码的复用性
特点
Java只支持单继承,不支持多继承,但支持多层集成
单继承:一个子类孩子能继承一个父类
多继承:子类不能同时继承多个父类
==注:==每一个类都直接或简介的继承于Object 类
子类可以继承父类中那些内容?
构造方法:构造方法不能被子类继承(任何修饰符下都不允许)
成员变量:成员变量可以被子类继承
成员方法:成员方法可以被子类继承(private修饰的成员方法无法被子类继承)
虚方法表:非private,非static,非final
注:为了提高性能,继承时,会创建父类成员方法的虚方法表(包括:非private,非static,非final 的方法)
成员变量的访问特点
就近原则:谁离我近,我就用谁
现在局部位置找,本类成员位置找,父类位置找,逐级往上
this:从本类成员位置开始往上找
super:从父类成员位置开始往上找
成员方法的访问特点
直接调用满足就近原则
super调用,会直接访问父类
方法的重写
当父类的方法不能满足子类现在的需求时,需要进行方法的重写
格式:在继承体系中,子类出现了和父类中一模一样的方法声明,我们就称子类这个方法是重写的方法。
☆
重写注解:@Override 放在重写后的方法上,校验子类重写时语法是否正确
重写的本质:如果发生了重写,子类虚方法表内的该方法会被覆盖
调用:this调用,就近原则;super调用,直接找父类。
注意事项与要求:
- 重写方法的名称、形参列表(参数)与父类中的保持一致
- 子类重写父类方法时,访问权限子类必须大于等于父类
- 子类重写父类方法时,返回值类型必须小于等于父类
- 建议:重写的方法尽量和父类保持一致
只有被添加到虚方法表中的方法才能被重写(非private,非static,非final 的方法)
构造方法的访问特点
父类中的构造方法不能被子类继承
子类中所有的构造方法默认先访问父类中的无参构造,再执行自己。
(子类在初始化的时候,有可能会使用到父类中的数据,如果父类没有完成初始化,子类将无法使用父类的数据。)
子类初始化之前,一定要调用父类构造方法先完成父类数据空间的初始化。
子类构造方法的第一行语句默认都是:super(),不写也存在,且必须放在第一行
如果想调用父类的有参构造,必须手写super()进行调用
多态
应用场景
拥有多个参数对象的方法,传入不同的对象,调用不同的方法
什么是多态
同类型的对象,表现出的不同形态(对象的多种形态)
表现形式:父类类型 对象名称 = 子类对象
多态的前提:有继承或实现关系
有父类引用指向子类对象
有方法重写
优点:使用父类型作为参数,可以接受所有子类对象,体现多态的扩展性与便利
在多态形式下,右边对象可以实现解耦合,便于扩展和维护。
定义方法的时候,使用父类型作为参数,可以接收所有子类对象,体现多态的扩展性与便利。
缺点:不能调用子类的特有功能
多态动用成员变量
(继承了父类中的成员变量)
编译看左边,运行也看左边
多态动用成员方法
(重写了父类中的方法)
编译看左边,运行看右边
instanceof 关键字
a instanceof B
判断a 是不是B的子类, 返回值boolean
JDK14新特性:
a instanceof B c //先判断a是不是B的子类,如果是转换为B类变量名为c,不是返回false
对象的强制转换
多态:向上转型
强转:向下转型
可以转换为真正的子类类型,从而调用子类独有的功能,在转换过程中可能存在类型不一致导致报错,在强转时使用instanceof关键字进行判断
包
包就是文件夹。用来管理何种不同功能的Java类,方便后期代码维护
规则:域名反写+包的作用,需要全部小写英文,见名知意
- 使用同一个包中的类时,不需要导包
- 使用java.lang包中的类时,不需要导包
- 其他情况都需要导包
- 如果同时使用两个包中的同类名,需要用全类名
final
可修饰类,方法,变量
修饰类:表示该类时最终类,不能被继承
修饰方法时: 表名该方法时最终方法,不能被重写
修饰变量:叫做常量,只能被赋值一次,后期无法被修改
常量
在实际开发中,常量一般作为系统的配置信息,方便维护,提高可读性
命名规范:
- 单个单词:全部大写
- 多个单词:全部大写,单词之间用下划线隔开
细节:
- final修饰的变量是基本类型:那么变量存储的数据值不能发生改变
- final修饰的变量是引用类型:那么变量存储的地址值不能发生改变,对象内部的可以改变
权限修饰符
用来控制一个成员能够被访问的范围,可修饰成员变量,方法,构造方法,内部类
private < 空着不写(缺省/默认) < protected < public
作用范围:
在实际开发中,一般只用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的新特性:接口中可以定义私有方法
接口和类之间的关系
类和类之间的关系:继承关系,只能单继承,不能多继承,但是可以多层继承
类和接口之间的关系:实现关系,也可以多实现,还可以在继承一个类的同时实现多个接口
接口和接口之间的关系:继承关系,可以单继承,也可以多继承
如果实现类实现了最下面的子接口,那么就需要重写所有的抽象方法
拓展
JDK8开始接口中新增的方法
JDK7以前:接口中只能定义抽象方法
JDK8的新特性:接口中可以定义有方法体的方法(默认:default,静态:static)
默认:
格式:public default 返回值类型 方法名(参数列表){ }
public default void show(){ }
注意:默认方法不是抽象方法,所以不强制被重写。但如果被重写,重写的 时候去掉default关键字
public可以省略,default不能省略
如果实现了多个接口,多个接口中存在的相同名字的默认方法,子类 就必须对该方法进行重写
静态: 允许接口中定义静态方法,需要用static修饰
格式:public static 返回值类型 方法名(参数列表){}
public static void show(){}
注意:静态方法只能通过接口名调用,不能通过实现类名或者对象名调用
public可以省略,static不能省略
JDK9的新特性:接口中可以定义私有方法
格式:① private 返回值类型 方法名(参数列表){}
private void show(){}
② private static 返回值类型 方法名(参数列表){}
private static void show(){}
静态的方法只能被静态的方法调用(混圈子)
接口的应用
-
接口代表规则,是行为的抽象。想要让哪个类拥有一个行为,就让这个实现类对应的接口就可以
-
当一个方法的参数是接口时,可以传递接口所有实现类的对象,这种方式称为接口多态
适配器的设置
设计模式(Design pattern):是一套被反复使用、多数人只晓的、经过分类编目的、代码设计经验的总结。实用设计模式是为了可复用代码、让代码更容易被他人理解、保证代码可靠性、程序的复用性
简单理解:设计模式就是解决各种问题的套路
适配器设计模式:解决接口与接口之间的矛盾问题
使一个抽象适配类==(使用abstract修饰)==空实现接口中的全部抽象方法,该接口的实现类去继承该接口的抽象适配类,并重写所需要的方法,从而间接的调用单独或某些接口
为了避免其他类创建适配器的对象,适配器类使用abstract修饰
适配器:Adapter
内部类
在一个类的里面,在定义一个类
规定:内部类表示的事物是外部类的一部分,内部类单独出现没有任何意义
特点:内部类可以直接访问外部类的成员,包括私有
外部类要访问内部类的成员,必须创建对象
成员内部类
写在成员位置,属于外部类的成员
可被一些修饰符所修饰:private,默认,protected,public,static等
在成员内部类里面,JDK16之前不能定义静态变量,JDK16开始才可以定义静态变量
内部类的创建:
①:
当成员内部类被private修饰时,外部类编写方法,对外提供内部类对象
②:
外部类名.内部类名 对象名 = new 外部类对象.new 内部类对象();
Outer.Inner name = new Outer().new Inner();获取外部的成员变量:外部类.this.变量名Outer.this.a
静态内部类
成员内部类的特殊情况。
静态内部类只能访问外部类中的静态变量和静态方法,如果想要访问非静态的需要创建对象。
静态内部类创建格式:外部类名.内部类名 对象名= new 外部类名.内部类名();
静态内部类调用格式:先创建对象,用对象调用
局部内部类
将内部类定义在方法里面就叫做局部内部类,类似于方法里面的局部变量
外界是无法直接使用,需要在方法内部创建对象并使用
该类可以直接访问外部类的成员,也可以访问方法内的局部变量
匿名内部类
本质上就是隐藏了名字的内部类,可以写在成员位置,也可以写在局部位置
格式:
new 类名或接口名(){重写方法;
};
格式细节: 包含了继承或实现,方法重写,创建对象
整体就是一个类的子类对象或接口的实现类对象