抽象类
定义
由于并不是所有对象都可以通过类去描述,如果一个类中没有包含足够的信息去描述一个对象,这样的类就是抽象类,含有抽象方法的类叫做抽象类,但值得注意的是抽象类不一定含有抽象方法
抽象方法的定义
抽象方法定义格式:
public abstract 返回值类型 方法名(参数);
抽象类定义的格式:
abstract class Shape{
public int index;
public Shape(){
}
public abstract double countPerimeter();
public abstract double countArea();
public abstract String getType();
}
class Circle extends Shape{
public double radius; //半径
public double countPerimeter() {
return 0;
}
public double countArea() {
return 0;
}
public String getType() {
return null;
}
}
使用抽象类的规则:
- 抽象类不能实例化对象 不能使用new操作符创建对象
- 抽象类的其他功能都与普通类一样
- 抽象类中可以定义构造器,但是不可以用来实例化对象,只能在子类中使用,所以该构造器一般定义为protected
特点
- 含有抽象方法 抽象类
- 不含抽象方法 普通类
- 抽象类必须被继承才能使用
- 抽象类和抽象方法都必须用abstract关键字修饰,抽象方法一定要定义在抽象类中
- 抽象类除了不能实例化对象之外,类的其他功能依然存在
- 抽象的子类可以重写抽象方法,也可以不重写 、
①不重写:不想重写抽象方法,该子类也是一个抽象类
②重写:重写所有的抽象方法,这个时候子类是一个具体的类
在抽象类中应注意的问题
- 抽象类相当于一个父亲,不断地从中抽取
- 不应该让类去创建对象,方法可以直接让子类去使用
- Private: 私有的方法子类是无法继承的,也不存在覆盖
Abstract和private也是不可以一起使用的
接口
接口只能含有抽象方法,接口定义式需要使用interface关键字,编译之后还是Class文件格式
interface interfaceName{
int index; //public static final (final(常量 编译时期就能够确定它的值))
void func(); //只能有方法的声明而不能存在方法的实现 public
}
使用接口的注意事项:
1)不能够new创建对象
2)如果要去创建一个接口对应的对象,则需要通过它的具体实现类,使用implements关键字去实现接口
3) 接口被编译之后也会产生对应的字节码文件
4)接口之间也是可以相互继承 extends
5) 接口对应是多实现 eg.class C implements A,B
6) 抽象类中设置的都是通用的方法,功能与实体都是一种"是"的关系, 接口中功能与实体都是一种"有"的关系
7)接口中定义的属性为什么是static final的?
static 原因主要是接口的实现是多实现,为了区分不同接口当中的相同变量
final 原因是因为如果是变量,接口的存在就失去其意义,同时接口来说指的是统一的协议,Java设计者直接规定接口中的属性只能是public static final的
8)Jdk1.8引入的新特性:
a.引入了default关键字提供默认接口方法,一个默认接口方法可以有默认的实现
作用如下:
①帮助扩展接口,而不需要破坏实现类
②接口和抽象类之间差异更小一点
③实现类可以自己决定覆盖哪个默认方法实现
④为了支持lambda表达式
b.允许接口中存在静态的公有方法
作用:
①可以用于提供一些合法性检查的逻辑
②静态方法不允许类重写,重写就会被覆盖,更加安全
比较器接口
内部比较器(Comparable接口)
如果需要让一个类中对象可比较,则当前的类必须要实现Comparable接口,重写compareTo方法,使得当前类对象按照compareTo方法中逻辑进行比较
class A implements Comparable{
// 重写CompareTo方法
public int compareTo(Object obj){
//固定使用某种逻辑进行比较
}
}
缺点:如果要更换比较逻辑,则需要修改原类,所以引入了compartor接口
外部比较器(Comparator接口)
jdk1.8 比较器接口 Comparator 不用修改原类,用来实现单独的比较器,前面介绍的Comparable接口中如果想要修改其比较逻辑,相当于修改原类中的compareTo方法,Compartor可以定义单独比较器,而不用修改原类,只需要修改调用法。
Comparable接口
public int compareTo(Object o) {
//this.name 与 o.name进行比较
return this.name.compareTo(((Person)o).name);
}
public int compareTo(Object o) {
//this.age 与 o.age进行比较
return this.age - ((Person)o).age;
}
Compartor接口
//按照name去进行比较
class NameComparator implements Comparator{
@Override
public int compare(Object o1, Object o2) {
return ((Person)o1).getName().compareTo(((Person)o2).getName());
}
}
//按照age
class AgeComparator implements Comparator{
@Override
public int compare(Object o1, Object o2) {
return ((Person)o1).getAge() - (((Person)o2).getAge());
}
}
Comparable与Comparator的区别
1)Comparator位于包java.util下,而Comparable位于包 java.lang下
2)Comparable 是一个对象本身就已经支持自比较所需要实现的接口(如 String、Integer 自己就可以完成比较大小操作,已经实现了Comparable接口)而 Comparator 是一个专用的比较器,当这个对象不支持自比较或者自比较函数不能满足你的要求时,你可以写一个比较器来完成两个对象之间大小的比较。
可以说一个是自已完成比较,一个是外部程序实现比较的差别而已。
Arrays.sort()用法理解
Java的Arrays类中有一个sort()方法,该方法是Arrays类的静态方法,在需要对数组进行排序时,可以直接调用。具体使用方法可以参照下面这篇文章。
Cloneable 标记接口
clone方法在Object类中定义为protected
因为protected受保护成员,分为与父类在同一包内和不在同一包内的子类,不在同一个包中的子类,只能访问从父类继承而来的受保护成员,而不能访问父类实例本身的受保护成员,在相同包内则没有以上的限制。并不是所有的对象都可以被克隆,如果子类对象可被克隆,则必须实现Cloneable接口并且重写clone方法。
如果一个类实现了Cloneable接口,就表示该类中的对象是可以被clone的,同时实现Cloneable则需要重写Object.clone方法。
接口和抽象的区别
- 相同点:
位于继承的顶端,用于被其他类实现或继承;
都不能直接实例化对象;
都可以包含抽象方法,其子类都必须覆写这些抽象方法;
- 区别:
抽象类为部分方法提供实现,避免子类重复实现这些方法,提高代码重用性;接口只能包含抽象方法;
一个类只能继承一个直接父类(可能是抽象类),却可以实现多个接口;(接口弥Java的单继承)
抽象类是这个事物中应该具备的内容, 继承体系是一种 is…a关系
接口是这个事物中的额外内容,继承体系是一种 like…a关系
- 二者的选用:
优先选用接口,尽量少用抽象类;
需要定义子类的行为,又要为子类提供共性功能时才选用抽象类;