抽象类
抽象方法:使用abstract修饰,且没有方法体的方法是抽象方法,语法如下:
abstract void f();
抽象方法并不等于空方法体,空方法体的语法如下:
void f(){}
同理,抽象类也必须使用abstract修饰,语法如下:
public abstract class ClassName{}
这里需要注意的是:(1)若一个类包含了抽象方法,则该类必须为抽象类,即:即该类必须使用abstract修饰。但是抽象类不一定包含抽象方法。(2)抽象类不能被实例化,无法使用new关键字来调用抽象类的构造函数来创建抽象类的实例。但抽象类可以包含构造函数哦。只能通过子类调用器构造函数进行初始化,且子类必须重写父类全部抽象方法,否则子类只能为抽象类(3)抽象类可以包含成员变量、普通方法、成员方法,构造函数、初始化块(静态代码块)、内部类、枚举,还可以实现接口。总结起来是“有得有失”,“得”指的是抽象类多了一个能力:可以包含抽象方法;“失”指的抽象类失去了一个能力,抽象类不能创造实例。下面我们来demo一下。
/**
* @Date: 2018/9/11 11:14
* @Description:抽象类:飞机
*/
public abstract class Airplane {
//普通成员变量
String colour;
//静态变量
static int age;
static{
System.out.println("父类class的初始化");
}
//构造函数
public Airplane()
{
System.out.println("初始化一个父类飞机实例");
}
//抽象方法:每个飞机都有翅膀这个特征
public abstract void wing();
//普通方法
public void broadcast(){
System.out.println("我是一架父类飞机");
}
//静态方法
public static void colour(){
System.out.println("我是一楼黄色的飞机");
}
}
/**
* @Date: 2018/9/11 11:29
* @Description:
*/
public class CivilAviation extends Airplane {
static{
System.out.println("子类class的初始化");
}
public CivilAviation(){
System.out.println("初始化一个子类飞机实例");
}
@Override
public void wing() {
System.out.println("我是明航机:我有一对大的翅膀");
}
public static void main(String[] args) {
CivilAviation civilAviation=new CivilAviation();
civilAviation.wing();
civilAviation.broadcast();
Airplane.colour();
}
}
控制台结果:
父类class的初始化
子类class的初始化
初始化一个父类飞机实例
初始化一个子类飞机实例
我是明航机:我有一对大的翅膀
我是一架父类飞机
我是一楼黄色的飞机
当然,我上面的demo需要你已经理解继承的概念,主要是为了表明,抽象类可以拥有的哪些方法、属性。另外:(1)抽象方法不可以用static修饰的(编辑器会直接报错):抽象类是不能直接被实例化的,即不能被直接分配内存;而static修饰的方法在类实例化之前就已经别分配了内存,这样一来矛盾就出现了,所以抽象类中不能有静态的抽象方法,(2)抽象方法必须为public或者protected,若为private则不能被继承,也就失去了意义。
抽象类具有什么意义呢?
将子类具有相同共性的行为或者特性进行抽象,比如demo中的wing()方法,每个飞行器都有翅膀,但翅膀的特征是不是不一样?民航机器的很大,战斗机的很小,F22的机翼一体了,但他们都是飞机翅膀呀,是不用可以抽象出来呢?显然是可以的,抽象出父类作为子类的一个模板。
接口
接口是从多个相似类中抽象出来的行为规范,它是对行为的抽象,并使用interface代替class。接口中的所有方法都是抽象方法,即:都用abstract修饰。但java8有了改进,接口中运行定义默认方法(使用default修饰)和类方法(static修饰),可以有方法体。语法说明:(1)接口的修饰符只能使用public或者省略,省略则表示只能在具体相同包接口下才能访问该接口。(2)一个接口可以有多个父接口,但接口只能继承接口,不能继承类。 (3)接口中的变量会被隐式地指定为public static final变量,即静态常量。由于接口不能包含初始化块和静态代码块,故只能在定义时指定默认值。(4)接口中的方法会被默认的指定为方法会被隐式地指定为public abstract方法且只能是public abstract方法,实际开发中我们只需写返回值类型和方法名即可。(5)若实现类未重写接口中全部的方法(默认方法和类方法除外),则该实现类只能为抽象类。来demo一下吧。
/**
* @Date: 2018/9/11 14:17
* @Description:定义飞行器的共同行为准则,会飞
*/
public interface Airplane1 {
//每个飞机都有6个轮子。实际不一定哈
public static final int WHEEL=6;
//每个飞机是不是都会飞呢?
void fly();
default void test(){
System.out.println("接口中的默认方法");
}
//这是类方法,不是静态方法
static void test2(){
System.out.println("接口中的类方法");
}
}
/**
* @Date: 2018/9/11 14:23
* @Description:
*/
public class Warcraft implements Airplane1{
@Override
public void fly() {
System.out.println("战斗机飞的快:超音速");
}
public static void main(String[] args) {
Warcraft warcraft=new Warcraft();
warcraft.fly();
warcraft.test();
Airplane1.test2();
System.out.println("战斗机中轮子的数量:"+Airplane1.WHEEL);
}
}
控制台结果:
战斗机飞的快:超音速
接口中的默认方法
接口中的类方法
战斗机中轮子的数量:6
另外 ,在JAVA中,类只能单继承,但可以实现多个接口:
class ClassName implements Interface1,Interface2,[....]{
}
抽象类和接口的区别:
语法上:(1)抽象类可以包含成员方法、抽象方法、成员属性、静态属性、静态代码块、初始化函数(其实除了不能利用new类创建以为,与普通类区别不大)。而接口中只能含义静态常量(public static final),只能存在public abstract 方法(JAVA8多了默认方法和类方法,这两个是可以有方法体的)(2)一个类只能继承一个抽象类,而一个接口可以实习多个接口
思想上:抽象类是对某些共性的抽象,或者说为子类提供了一个公共的模板。而接口则是为其子类提供了一套公共的行为准则,一旦接口被改变,它对整个系统的影响是辐射式的,其实现类必须全部改写。