面向对象编程(OOP)的高级特性
oop的高级特性
- 封装,继承,多态
继承
继承是面向对象语言的高级特性,它的作用是简化类的设计,让子类可以直接拥有父的属性和方法,而无需重复定义
java中的继承
- java中只支持单继承,不支持多继承,但支持多层继承
- 在继承关系中,子类继承父类,子类和父类都是相对的概念
- 我们可以使用 is 来判断是否可以使用继承,即子类 is 一个特殊的父类
- 继承的语法是
class 子类名 extends 父类{
}
重写方法(override)
在继承关系下,子类覆盖父类的方法; (方法名相同参数相同,返回值类型小于父类返回值)
关于继承的小结
- 父类有的,子类一定有
- 父类没有的,子类可以增加
- 父类有的,子类可以修改(方法重写、覆盖)
子类中也可以定义一个父类中同名的属性;这种操作被称为覆盖
子类中访问父类的成员:
super关键字:这个关键字代表父类对象的引用,通过super.我们可访问父类的属性及方法。
子类对象的内存结构
当我们实例化一个子类对象时,会首先在内存中创建一个父类的对象,然后再创建子类的对象。
关于子类的构造方法
- 普通方法可以继承,构造方法不能继承。但在子类的构造方法中一定要先调用父类的构造方法,如果不明确指定调用父类的哪个构造方法,将会隐式的调用父类无参的构造方法。
- 子类的构造方法可以通过super()来明确调用父类的构造方法;super()必须放在子类构造方法的第一行;并用只能调用 一次。
多态
同一类事物拥有多种不同的形态
多态指的就是子类的对象赋给父类的引用
使用多态时,java中有两种数据类型,编译时类型和运行时类型
- 编译期类型:定义变量的那个类型,在编译期就能确定,它可以确定能使用哪些方法;
- 运行期类型;运行代码时确定的类型;在运行期才能确定,编译期无法确定,通过它能决定运行时执行的具体方法。
多态中的类型转换(造型)
- 向上转型(upcast):子类对象可以直接赋给父类的引用;
- 向下转型 (downcast):将父类的类型转换成子类的类型。需要使用(子类型)强转,可能会出现ClassCastException异常的风险。
instanceof 运算符
作用:判断某个对象是否是某个类的实例
注意:为了确保代码的强壮性,在转换之前要先做一个instanceof判断。
封装
- 信息隐藏
封装的三个体现
- 类本身就是一个封装体
- 方法也是一种封装
- 通过访问修饰符来限制成员的访问级别
四个访问修饰符
修饰符 | 类内部 | 同包 | 不同包子类 | 不同包非子类 |
---|---|---|---|---|
private | y | n | n | n |
默认 | y | y | n | n |
protected | y | y | y | n |
public | y | y | y | y |
关于访问器
java中建议属性都设置为private,如果需要访问属性,可以定义两个方法对其进行访问,这两个方法被称为访问器,setter,getter
方法重写重新学习
- 方法名相同,参数相同
- 修饰符:子类可以大于父类
- 返回值:子类方法的返回值 可以是父类的子类
final修饰符
- 属性:不能被重新赋值 ,常量
- 方法:不能被重写
- 类 : 不能被继承
static :静态的
- 修饰属性:被修饰的属性是属于类的,而不是属性对象的;访问static 属性时,可以不创建对象,直接使用 类名.属性名 访问
- 修改方法:被修饰的方法可以直接通过 类名.方法名 来访问,在static方体中只能使用静态成员;也不能使用this,super关键字
静态方法的使用注意事项
- 静态方法只能直接使用静态成员(静态方法及静态属性),而不能使用非静态成员
- 静态方法中,不能使用this,super关键字
- 调用静态方时,最好使用 类名.方法名 () 直接调用
静态块
static{
//代码;
}
作用:在类初始时执行;每个static 块只执行一次
如果有下列操作,将会提前运行static中的代码
- 实例化对象 new 对象
- 调用类的静态方法
- 使用类的静态成员
单例模式
解决的问题:
一个类只允许创建唯一的一个对象
解决办法
1.定义private的构造方法
2.定义一个static 的成员变量,类型是当前类的类型
3.提供一个公共的static方法,用来返回唯一的实例
public class TaskManager {
//2.在类的内部创建一个对象;
private static TaskManager manager=new TaskManager();
//1.私有的构造 方法;
private TaskManager() {
System.out.println("创建了一个任务管理器");
}
//3.定义一个静态方法,用来获得唯一的实例;
public static TaskManager getInstance() {
return manager;
}
public void showTasks() {
System.out.println("任务管理器已启动");
}
}
单例分两种
- 懒汉式:什么时侯用,什么时侯创建
- 饿汉式:无论用户是否调用,都提前创建好对象
abstract
- 抽象方法:只有方法定义,没有方法体
- 抽象类: 不能被实例化,只能被继承
关于抽象类的说明
- 抽象类不能被实例化,抽象类就是为了被继承用的
- 如果一个类中包含至少一个抽象方法,那么这类就是抽象类
- 抽象类中也可以包含属性,普通方法和构造方法
- 如果一个子类的父类是一个抽象类,它必须重写所有抽象方法,否则它还是一个抽象类
接口
- 接口是一个特殊的抽象类
- 接口中只能有public static final修饰的属性;
- 只能有抽象方法(public abstract)
如何定义一个接口
interface 接口名{
}
接口通常只是表示一种能力;而抽象类表示一类事物
接口与抽象类的区别:
- 抽象类中可以有普通方法,抽象方法,构造方法,普通属性,而接口中只能包括抽象方法及公有的静态常量
- 一个类只能有一个父类;一个类可以实现多个接口,一个接口可以继承多个接口
- 抽象类通常表示一类事物,而接口表示一种能力
java8中接口的新特性
- java8以后接口中可以使用default关键字修饰方法,子类默认继承,子类可以不用强制重写(可以有方法体)
- java8以后接口中可以使用static关键字修饰方法,可以使用类.方法名调用,子类中不能调用(可以有方法体)
内部类
静态内部类
成员内部类
方法内部类
匿名内部类
构造方法的补充
匿名块:作用是在构造方法之前调用,无论调用的是哪个构造方法,都会先调用此匿名块;
{
//代码;
}
this()
在类中的一个构造方法中可以通过this()来调用其它的构造方法,this()只能在构造方法中调用,同时必须放在第一行.