一、抽象类和接口
1.抽象类
- 抽象方法: 没有方法体的方法。
//就是加上abstract 关键字,去掉大括号,直接分号结束 - 抽象类:包含抽象方法的类。从众多类中抽取共同特性叫抽象类
//抽象方法所在类必须是抽象类,在class之前写上abstract - 抽象方法的设计原则 : 设计和实现相分离
只做设计 继承其的子类必须重写(除非子类是更小的抽象类) - 如何使用抽象类:
- 不能直接创建抽象类的对象
- 必须用一个子类继承抽象类
- 子类必须覆盖重写(实现)父类的所有抽象方法
子类去掉abstract关键字,补上大括号 - 创建子类对象实现
- 抽象类注意事项:
- 抽象类不能创建对象,如果创建编译报错
- 抽象类中一定有构造方法,是供子类创建对象实现,初始化父类成员使用的
- 抽象类不一定对含有抽象方法,但是有抽象方法一定是抽象类,
是为了某些特殊的类的结构设计不想让调用者创建其对象 - 抽象类的子类必须重写父类的所有抽象方法,否则编译报错。除非子类也是一个抽象类
2.接口
-
概念:
- 接口就是一种公共的规范标准,只要符合规范标准,大家都可以通用。Java中的接口更多的体现在对行为的抽象!
- 接口就是多个类的公共规范
- 接口是一种引用数据类型,其中含有抽象方法
//更抽象的抽象方法
-
作用:
解决想要多继承 深继承的原因
like a 像一个
解决冗余,不是类 -
定义格式:
- 接口定义
public interface 接口名 {
//接口内容
}
ps:换成了关键字interface之后,编译生成的字节码文件仍然是 .java----.class
- 接口其他内容定义
java8包含
- 常量
- 抽象方法
- 默认方法
- 静态方法
1.抽象方法定义:
(public abstract) 返回值类型 方法名称(参数列表);
实现类必须重写抽象方法
2.默认方法定义:
(public) default 返回值类型 方法名称(参数列表){
}
实现类可以不实现默认方法
3.静态方法定义:
(public) static 返回值类型 方法名称(参数列表){
}
接口名称.方法名称()调用
4.常量定义:
(public static final) 常量名称 =值;
- 接口的成员变量都是公有的静态常量,必须赋值,不可修改
- 常量名称使用完全大写
-
如何使用接口:
-
接口不能直接使用,必须有一个实现类来实现该接口
格式: -
接口的实现类必须覆盖重写接口中所有的抽象方法
实现 去掉abstract 关键字,加上方法体大括号 -
创建实现类的对象进行调用
-
public class 实现类名称 implements 接口名称{
//...
}
- 接口注意事项:
- 接口没有静态代码块或者构造方法
- 类与类之间是单继承的,但是类可以实现多个接口。接口之间是多继承的
- 如果实现类实现的多个接口当中村早重复的抽象方法,只需要覆盖重写一次
- 如果实现类没有哦覆盖重写所有的抽象方法,那么实现类必须是一个抽象类
- 如果实现类的多个接口当中存在重复的默认方法, 实现类必须对冲突的默认方法啊进行重写,而且必须带着default关键字
3.抽象类和接口的相同和不同
- 相同:抽象类和接口都是用抽象方法,设计实现相分离
- 区别:
- 抽象类有构造方法是类 接口没有构造方法,不是类
- 抽象类关键字是abstract ,可以有非抽象方法 ;接口关键字 interface 只有抽象方法
- 抽象类只能被继承extends ,只能单继承;接口被实现implements 可以多实现
- 接口只能做方法申明,抽象类中可以做方法申明,也可以做方法实现
- 抽象类可以继承抽象类,接口不能实现接口,但是可以多继承接口
- 抽象类类级别的抽象 —类 ;接口方法级别的抽象–方法
2.多态
- extends 继承或者 implements 实现是多态的前提
- 父类声明,子类实例化 /父类引用指向子类对象
1.定义格式:
-
父类名称 对象名 =
new
子类名称();
接口名称 对象名=
new
实现类名称();
-
任何自定义的类和接口都可以作为变量类型和参数、返回值类型
2.多态下的访问
-
总体说法
成员变量- 直接通过变量名称访问成员变量 看等号左边是谁,优先用谁,没有则往上找
- 间接通过成员方法访问成员变量 看方法属于谁,优先用谁,否则往上找
成员方法 - 在多态的代码中成员方法,看new的是谁,就优先谁,否则往上找
口诀: 编译看左,运行看右
-
换一种说法 多态时的说法
1.编译时认为是父类的
2.运行时认为是子类的
3.拥有父类的属性
4.占用子类的内存空间
(子类方法覆盖父类的方法时,此时对象调用的是子类的方法;
否则,自动调用从父类继承的方法)
3.内部类
- 如果一个类的内部包含另一个事务,那么这就是一个类内部包含另一个类
- 成员内部类
局部内部类(包含匿名内部类)
1.定义格式
成员内部类
1.修饰符 class 外部类名称{
修饰符class 内部类名称{
//...
}
//...
}
2.注意:内用外,随便访问;外用内 ,需要内部对象
局部内部类
1.局部内部类,定义在方法内部,只有所属的方法能调用。超出方法就无法使用
2. 修饰符 返回值类型 外部方法名称(参数列表){
class 局部内部类名称{
//...
}
//...
}
3.如果希望访问所在方法的局部变量,那么这个局部标量必须是有效final修饰
2.两者访问权限
- 外部类 :public /(default)
- 成员内部类:public /protected/(default)/private
- 局部内部类:什么修饰符都不能写
3.匿名内部类
如果接口的实现类或者继承的子类只需要使用唯一的一次,那么这种情况下可以省略掉该类的定义,而使用匿名内部类
- 定义格式:
接口名称 对象名 =new 接口名称(){
//覆盖重写所有的抽象方法
}
//new 接口名称(){}就是匿名的实现类对象
- 注意事项:
- 匿名内部类,在创建对象的时候只能使用唯一一次
如果希望多次创建对象,并且内容一样就必须单独定义实现类
- 匿名对象,在调用方法的时候只能调用唯一一次
如果希望多次调用,必须单独创建该对象
- 匿名内部类是省略 实现类/子类,但是匿名对象是省略了对象名称
注意区分
四、设计模式
1.单例模式
分类:懒汉式、饿汉式
-
构造方法私有化
-
在本类中创建本类对象
-
保证对象的唯一性final
-
给外界提供得到对象的方法 static
-
在多线程中,饿汉式安全,懒汉式不安全
2.简单工厂模式
批量创建对象
-
创建工厂类 : 创建对象的方法
-
果汁类 是所有种类果汁的父类
-
在工厂类的方法中返回果汁类
-
根据测试类中传递的字符串判断到底返回哪种果汁
-
测试类通过工厂类返回果汁对象
3.建造者模式
内部类使用场景
目的:静态内部类创建外部类对象
-
创建外部类,在其中创建一个静态内部类
-
静态内部类中写属性,构造方法和set get方法
-
静态内部类中写一个方法,必须返回外部类对象
-
给外部类创建对象,传递参数。
4.装饰者模式
-
在处理流中使用
-
子类重写父类的方法,提高父类方法的功能及效率
-
为了尽可能减少重复代码,在重写的方法中用父类的对象调用父类原来的方法
-
得到父类对象可以通过将父类对象作为子类属性,通过子类构造方法传递父类对象