目录
一、抽象类
定义
由于并不是所有对象都可以通过类去描述。如果一个类中没有包含足够的信息去描述一个对象,这样的类就是抽象类。用关键字abstract修饰,抽象类是一种没有完全实现的类。不能用它来实例化对象,它的主要用途是用来描述一些概念性的内容,然后在子类中去具体实现这些概念,一般抽象类都是作为其他类的父类。
例:
abstract class Shape{
private int index;
public abstract int CalculateArea();
public abstract int CalculateGirth();
}
class Ciecle extends Shape{//圆作为形状的子类去继承
private int r;
public int CalculateArea(){//方法重写
s = pi*r*r;
return s;
}
public int CalculateGirth(){
c = 2*pi*r;
}
}
特点
1.抽象类和抽象方法都必须用abstract关键字修饰
2.抽象类中不一定有抽象方法,但是有抽象方法的类必须定义为抽象类
3.抽象类不能实例化
4.抽象的子类可以重写抽象方法,也可以不重写
a.不重写:不想重写抽象方法,该子类也是一个抽象类
b.重写:重写所有的抽象方法,这个时候子类是一个具体的类
声明格式
抽象类的实例是靠具体的子类实现的,是多态的方式
Shape s = new Circle;
成员特点
成员变量:既可以是变量,也可以是常量
构造方法:有,用于实现子类访问父类数据的初始化
注意:抽象类中可以定义构造器,但是不可以用来实例化对象,只能在子类中使用,所以该构造器一般定义为protected
成员方法:可以是抽象的,也可以是非抽象的
抽象类and抽象方法
抽象类中可以含有抽象方法,抽象方法只有方法的返回值、名称、参数列表,没有方法体,它必须在子类中给出具体实现方法。
1.用abstract关键字修饰的类叫抽象类
2.用abstract关键字修饰的方法叫抽象方法
3.含有抽象方法的类必须声明为抽象类
4.抽象类必须被继承,抽象方法必须被重写
5.只给出具体方法,不给其他实现的方法称为抽象方法,抽象方法是没有方法体的,在代码的表达上就是没有“{}”
例:
6.抽象类除了包含抽象方法外,还可以包含其他具体的变量和具体的方法。类即使不包含抽象方法,也可以被声明为抽象类,防止被实例化。
7.抽象类不能被实例化,不能使用new操作符创建对象,抽象方法必须在子类中实现。
8.抽象类不能直接使用,必须用子类去实现抽象类,然后使用其子类的实例。
二、接口
定义
抽象层级的概念,接口是抽象类的一种变体,用关键字interface来修饰,并且接口中所有方法都是抽象的,也没有方法体,在代码的表达上也是没有“{}”。
形式:
[修饰符] interface 接口名
{
…//变量声明和方法声明
}
接口的实现
有接口生成子类,使用关键字implements来实现
形式:
class 类名 implements 接口名
{
…//类体
}
成员特点
1.成员变量:只能是常量,并且必须是静态的
默认修饰符:public static final
原因:
static 原因主要是接口的实现是多实现,为了区分不同接口当中的相同变量
final 原因是因为如果是变量,接口的存在就失去其意义
2.构造方法:接口没有构造方法
3.成员方法:只能是抽象方法
默认修饰符:public abstract
使用接口注意事项
1.不能够new创建对象
2.如果要去创建一个接口对应的对象,则需要通过它的具体实现类,使用implements关键字去实现接口
3.接口被编译之后也会产生对应的字节码文件
4.接口之间也是可以相互继承 extends
5.接口对应是多实现 eg.class C implements A,B (相当于实现了Java的多继承)
例:
interface A{
int a = 1;
void func1();
}
interface B{
int b = 2;
void func2();
}
interface C extends A,B{//C继承A,B
int c = 3;
void func3();
}
6.Jdk1.8引入的新特性:
a.引入了default关键字提供默认接口方法,一个默认接口方法可以有默认的实现
作用如下:
帮助扩展接口,而不需要破坏实现类
接口和抽象类之间差异更小一点
实现类可以自己决定覆盖哪个默认方法实现
为了支持lambda表达式
b.允许接口中存在静态的公有方法
作用:
可以用于提供一些合法性检查的逻辑
静态方法不允许类重写,重写就会被覆盖,更加安全
特殊的接口
比较器接口
Comparable接口
如果需要让一个类中对象可比较,则当前的类必须要实现Comparable接口,重写compareTo方法,使得当前类对象按照compareTo方法中逻辑进行比较
class A implements Comparable{
// 重写CompareTo方法
public int compareTo(Object obj){
//固定使用某种逻辑进行比较
}
}
缺点:如果要更换比较逻辑,则需要修改原类,所以引入了compartor接口
Compartor接口
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());
}
}
Cloneable接口
如果一个类实现了Cloneable接口,就表示该类中的对象是可以被clone的,同时实现Cloneable则需要重写Object.clone方法
clone方法在Object类中定义为protected
因为protected受保护成员,分为与父类在同一包内和不在同一包内的子类,不在同一个包中的子类,只能访问从父类继承而来的受保护成员,而不能访问父类实例本身的受保护成员,在相同包内则没有以上的限制。并不是所有的对象都可以被克隆,如果子类对象可被克隆,则必须实现Cloneable接口并且重写clone方法。
三、区别与联系
外观
1.关键字
抽象类用到abstract关键字修饰一个class类,表示抽象类;
接口使用interface关键字;
2.定义方法
抽象类中可以定义抽象方法也可以定义普通的成员方法,接口中的方法jdk1.8之前只有方法的声明没有方法的实现,而jdk1.8之后可以定义default默认实现的方法,也可以定义static静态方法;
3.定义变量
抽象类中可以定义任意变量、常量,接口中只能定义public static final常量;
4.继承
抽象类使用extends关键字去继承,继承只能是单继承,接口使用
implements关键字去实现,实现可以是多个实现
使用
5.创建对象
抽象类和接口本身不能使用new操作符创建一个对象;
6.构造方法
抽象类中可以定义构造方法的,接口中不能定义构造方法,抽象类中的构造方法一般是protected修饰的,因为其构造方法的定义是为了方便子类所使用;
7.注意
抽象类和接口中的抽象方法不能够是private,如果是private子类则无法实现该方法。
个人见解
抽象类是一种"是"的关系,接口是一种"含有"的关系,实现这个接口就会含有这个功能,抽象类则是一种高度的概括,其中会定义一些通用的方法;
抽象类是应用于所有子类都有该方法,只是具体实现不同,接口是某些子类特有的方法,相当于c++中的多继承;
接口可以有多个实现, 所以灵活性和扩展性方面,接口会更强一些。