面向对象下
十六、 抽象
抽象类
被abstract所修饰的类
格式
【权限修饰符】 abstract class 类名{
}
【权限修饰符】 abstract class 类名 extends 父类{
}
抽象方法
没有方法体的方法
格式
【其他修饰符】 abstract 返回值类型 方法名(【形参列表】);
注意:抽象方法没有方法体
特点
- 1.抽象类不能创建对象,如果创建,编译无法通过而报错。只能创建其非抽象子类的对象。
- 2.抽象类中,也有构造方法,是供子类创建对象时,初始化父类成员变量使用的。
- 3.抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
- 4.抽象类的子类,必须重写抽象父类中所有的抽象方法,否则,编译无法通过而报错。除非该子类也是抽象类。
注意
- 1.抽象类中,可以存在普通的方法或欧通的属性
- 2.抽象类中可以没有抽象方法
- 3.抽象方法必须存在于抽象类中
- 4.一个类继承了抽象类,那么此类要么实现所有的抽象方法,要么该类也变成抽象类
- 5.抽象方法不能被static(静态)、private(私有)、final修饰
十七、 接口
17.1 概述
接口就是静态常量和抽象方法定义的集合
17.2 格式:
修饰符 interface 接口名{ }
17.3 作用:
用来定义规范
17.4 接口的实现
【修饰符】 interface 接口名{
}
接口是静态常量与抽象方法定义的集合。跟定义类的方式类似,接口使用关键字interface定义
17.5 注意
- 1.如果一个类实现了接口,那么此类需要实现接口内所有的抽象方法,否则此类要变为抽象类
- 2.接口不能直接创建对象
- 3.如果一个类实现了接口,可以把此类看成是该接口的孩子
17.6 接口的成员
- 接口的属性是全局静态变量,默认被public static final 修饰
- 接口内的抽象方法是全局抽象方法,默认被public abstract修饰
- 接口内可以有静态方法,默认被public修饰
- 接口内有默认方法,哪一个实现类需要重写,直接重写即可,不会对其他类造成影响。默认是被public修饰
17.7 特点
-
接口没有构造方法,不能创建对象
-
成员变量默认自带修饰符public static final,即为静态常量。
-
抽象方法默认自带修饰符public abstract(jdk8之前版本接口中方法只能是抽象方法)
-
接口是用来被实现的,其实现类必须重写它的所有抽象方法,除非实现类是个抽象类
-
接口可以多实现,一类可以同时实现多个接口
-
接口可以继承接口,接口之间支持多继承
-
接口中允许声明默认方法和静态方法
- 公共的默认的方法
- public 可以省略,建议保留,但是default不能省略
- 公共的静态的方法
- public 可以省略,建议保留,但是static不能省略
- 公共的默认的方法
-
在JDK1.9时,接口又增加了私有方法
17.8 经典接口
17.8.1 Comparable:内部比较器
定义
步骤
- 第一步:哪个类的对象要比较大小,那个类就得实现java.lang.Comparable接口,并重写compareTo方法
- 第二步:对象比较的时候,通过对象调用compareTo方法得到结果
- 若返回一个正数则说明当前对象大于传入对象
- 若返回0则说明两个对象相等
- 若返回一个负数则说明当前对象小于传入对象
Arrays.sort()
- 数组排序
17.8.2 Comparator:外部(定制)比较器
定义:可以在比较对象类的外部完成"比较规则"的制定
步骤
- 1.创建一个比较规则类,实现Comparator接口
- 2.重写compare(Object o1, Object o2);
- 在compare方法内需要完成比较规则的制定
- >0 前一个对象>后一个对象
- 0 前一个对象后一个对象
- <0 前一个对象<后一个对象
- 在compare方法内需要完成比较规则的制定
- 3.在需要比较对象的位置,创建比较规则类的对象
- 4.此对象调用compare();
Arrays.sort(arr, parameter);arr:需要排序的数组,parameter:排序的规则,即comparator接口实现类
17.8.3 Cloneable:标记接口(没有任何方法的接口,类似注解)
protected Object clone()throws CloneNotSupportedException
- 所有类都可以重写此方法,它是获取一个对象的克隆体对象用的,就是造一个和当前对象各种属性值一模一样的对象。当然地址肯定不同
- 在重写这个方法后时,调用super.clone(),发现报异常CloneNotSupportedException,因为我们没有实现java.lang.Cloneable接口
十八、 内部类
18.1 概述
定义:将一个类A定义在另一个类B里面,里面的那个类A就称为内部类,B则称为外部类。
为什么要声明内部类
当一个事物的内部,还有一个部分需要一个完整的结构进行描述,而这个内部的完整的结构又只为外部事物提供服务,不在其他地方单独使用,那么整个内部的完整结构最好使用内部类。而且内部类因为在外部类的里面,因此可以直接访问外部类的私有成员。
18.2 形式
18.2.1 成员内部类
静态成员内部类
-
格式
【修饰符】 class 外部类{ 【其他修饰符】 static class 内部类{ } }
-
特点
- 和其他类一样,它只是定义在外部类中的另一个完整的类结构
- 可以继承自己的想要继承的父类,实现自己想要实现的父接口们,和外部类的父类和父接口无关
- 可以在静态内部类中声明属性、方法、构造器等结构,包括静态成员
- 可以使用abstract修饰,因此它也可以被其他类继承
- 可以使用final修饰,表示不能被继承
- 编译后有自己的独立的字节码文件,只不过在内部类名前面冠以外部类名和 符 号 ( O u t e r 符号(Outer 符号(OuterInner.class)。
- 和外部类不同的是,它可以允许四种权限修饰符:public,protected,缺省,private
- 外部类只允许public或缺省的
- 只可以在静态内部类中使用外部类的静态成员
- 在静态内部类中不能使用外部类的非静态成员
- 在外部类的外面不需要通过外部类的对象就可以创建静态内部类的对象
- 如果在内部类中有变量与外部类的静态成员变量同名,可以使用“外部类名."进行区别
- 和其他类一样,它只是定义在外部类中的另一个完整的类结构
-
注意
- 1.静态内部类可以有静态的资源
- 2.可以直接使用外部类静态资源
非静态成员内部类
-
格式
【修饰符】 class 外部类{ 【修饰符】 class 内部类{ } }
-
特点
- 和其他类一样,它只是定义在外部类中的另一个完整的类结构
- 可以继承自己的想要继承的父类,实现自己想要实现的父接口们,和外部类的父类和父接口无关
- 可以在非静态内部类中声明属性、方法、构造器等结构,但是不允许声明静态成员,但是可以继承父类的静态成员,而且可以声明静态常量。
- 可以使用abstract修饰,因此它也可以被其他类继承
- 可以使用final修饰,表示不能被继承
- 编译后有自己的独立的字节码文件,只不过在内部类名前面冠以外部类名和$符号。
- 和外部类不同的是,它可以允许四种权限修饰符:public,protected,缺省,private
- 外部类只允许public或缺省的
- 还可以在非静态内部类中使用外部类的所有成员,哪怕是私有的
- 在外部类的静态成员中不可以使用非静态内部类哦
- 就如同静态方法中不能访问本类的非静态成员变量和非静态方法一样
- 在外部类的外面必须通过外部类的对象才能创建非静态内部类的对象
- 因此在非静态内部类的方法中有两个this对象,一个是外部类的this对象,一个是内部类的this对象
- 和其他类一样,它只是定义在外部类中的另一个完整的类结构
18.2.2 局部内部类
写在方法内的有名字的局部内部类
-
格式
【修饰符】 class 外部类{ 【修饰符】 返回值类型 方法名(【形参列表】){ 【final/abstract】 class 内部类{ } } }
-
特点
- 和外部类一样,它只是定义在外部类的某个方法中的另一个完整的类结构
- 可以继承自己的想要继承的父类,实现自己想要实现的父接口们,和外部类的父类和父接口无关
- 可以在局部内部类中声明属性、方法、构造器等结构,不能有静态资源,但可以有静态的常量
- 可以使用abstract修饰,因此它也可以被同一个方法的在它后面的其他内部类继承
- 可以使用final修饰,表示不能被继承
- 编译后有自己的独立的字节码文件,只不过在内部类名前面冠以外部类名$序号内部类名.class。
- 这里有编号是因为同一个外部类中,不同的方法中存在相同名称的局部内部类
- 若需要使用局部内部类资源则需要创建局部内部类对象
- 和成员内部类不同的是,它前面不能有权限修饰符等(即只能被default修饰)
- 局部内部类如同局部变量一样,有作用域
- 局部内部类地位比较低,使用什么资源是由所在方法决定
- 局部内部类中还可以使用所在方法的局部常量,即用final声明的局部变量
- — 在JDK1.8之后,如果某个局部变量在局部内部类中被使用了,自动加final
- 和外部类一样,它只是定义在外部类的某个方法中的另一个完整的类结构
-
思考:为什么在局部内部类中使用外部类方法的局部变量要加final呢?
如果外部类方法中的局部变量不是final的,那么外部类方法执行完,外部类方法的栈空间就释放了,那么变量也就消失了
匿名的内部类
-
定义:没有名字的内部类
-
作用
- 1.完成了该类匿名子类创建
- 2.完成了该类匿名子类对象创建
-
如何创建
-
1.匿名类实现:new 类(){ };
new 父类(【实参列表】){ 重写方法... } //()中是否需要【实参列表】,看你想要让这个匿名内部类调用父类的哪个构造器,如果调用父类的无参构造,那么()中就不用写参数,如果调用父类的有参构造,那么()中需要传入实参
- 注意:匿名内部类是没有名字的类,因此在声明类的同时就创建好了唯一的对象。
-
2.new 接口(){ };
new 父接口(){ 重写方法... } //()中没有参数,因为此时匿名内部类的父类是Object类,它只有一个无参构造
-
-
注意事项
- 1.匿名内部类有独立的字节码文件
- 命名方式为:外部类名$1.class,序号从1开始
可以使用abstract修饰,因此它也可以被同一个方法的在它后面的其他内部类继承 - 可以使用final修饰,表示不能被继承
- 编译后有自己的独立的字节码文件,只不过在内部类名前面冠以外部类名$序号内部类名.class。
- 这里有编号是因为同一个外部类中,不同的方法中存在相同名称的局部内部类
- 命名方式为:外部类名$1.class,序号从1开始
- 若需要使用局部内部类资源则需要创建局部内部类对象
- 和成员内部类不同的是,它前面不能有权限修饰符等(即只能被default修饰)
- 局部内部类如同局部变量一样,有作用域
- 局部内部类地位比较低,使用什么资源是由所在方法决定
- 局部内部类中还可以使用所在方法的局部常量,即用final声明的局部变量
- — 在JDK1.8之后,如果某个局部变量在局部内部类中被使用了,自动加final
- 1.匿名内部类有独立的字节码文件
-
思考:为什么在局部内部类中使用外部类方法的局部变量要加final呢?
如果外部类方法中的局部变量不是final的,那么外部类方法执行完,外部类方法的栈空间就释放了,那么变量也就消失了
匿名的内部类
-
定义:没有名字的内部类
-
作用
- 1.完成了该类匿名子类创建
- 2.完成了该类匿名子类对象创建
-
如何创建
-
1.匿名类实现:new 类(){ };
new 父类(【实参列表】){ 重写方法... } //()中是否需要【实参列表】,看你想要让这个匿名内部类调用父类的哪个构造器,如果调用父类的无参构造,那么()中就不用写参数,如果调用父类的有参构造,那么()中需要传入实参
- 注意:匿名内部类是没有名字的类,因此在声明类的同时就创建好了唯一的对象。
-
2.new 接口(){ };
new 父接口(){ 重写方法... } //()中没有参数,因为此时匿名内部类的父类是Object类,它只有一个无参构造
-
-
注意事项
- 1.匿名内部类有独立的字节码文件
- 命名方式为:外部类名$1.class,序号从1开始
- 2.匿名内部类是特殊的局部内部类
- 1.匿名内部类有独立的字节码文件