(三)、抽象类和接口的区别
一、抽象类(Abstract Class)
(一)概念
1.抽象类是关键字Abstract修饰的类,即为抽象类,但是没有方法体( 没有{ } ),只有声明方法,抽象方法强制子类覆盖。
2.抽象抽象即不能被实例化,不能创建对象(不能new, 但是可以super)。而不能被实例化就无用处,所以抽象类只能作为基类(父类),即被继承的类,即抽象类必须得有子类,自己的功能才能得以运行。
3.抽象类中可以包含抽象方法也可以不包含,但具有抽象方法的类一定是抽象类。
4.抽象类的方法只是定义了子类应该具备的行为,但是没有给出怎么去完成行为的功能代码,要交给子类去根据自身特殊情况去完成该父类申明的功能。
5.抽象类中可以有普通方法,可以声明成员变量。
(二)抽象类的使用原则
1.被继承性:抽象方法必须为public或者protected(因为如果为private,则不能被子类继承,子类便无法实现该方法),缺省情况下默认为public;
2.抽象性:抽象类不能直接实例化,需要依靠子类采用向上转型的方式处理;
3.抽象类必须要有子类,使用extends继承;
4.子类(如果不是抽象类)则必须重写抽象类中的全部抽象方法;如果子类没有实现父类的抽象方法,则必须将子类也定义为abstract类。
5.抽象类中的普通方法可以有选择型的来决定是否需要重写。
//抽象类 abstract class A{ //普通方法 public void fun(){ System.out.println("存在方法体的方法"); } //抽象方法,没有方法体,有abstract关键字作修饰 public abstract void print(); } //单继承特性 class B extends A{ //B类是抽象类的子类,是一个普通类 @Override public void print(){ //强制要求重写 System.out.println("Why is more important than what!"); } } //主函数 public class test{ public static void main(String[] args) { A a = new B(); //多态,向上转型 a.print(); a.fun(); //被子类所重写过的方法 } }
运行结果如下:
(三)为什么不能进行实例化?
当一个类实例化后,就意味着对象可以调用类中的属性或者方法,但在抽象类里存在抽象方法,而抽象方法没有方法体,没有方法体就无法进行调用,既然无法进行方法调用,又怎么去产生实例化对象呢。
(四)抽象类的使用限制
1.抽象类中有构造方法吗?
由于抽象类里会存在一些属性,那么抽象类一定存在构造方法,其存在目的就是为了属性的初始化。并且子类对象实例化的时候,依然满足先执行父类构造,再执行子类构造的顺序。
abstract class A{//定义一个抽象类 public A(){ System.out.println("*****A类构造方法*****"); } public abstract void print();//抽象方法,没有方法体,有abstract关键字做修饰 } //单继承 class B extends A{//B类是抽象类的子类,是一个普通类 public B(){ System.out.println("*****B类构造方法*****"); } @Override public void print(){//强制要求覆写 System.out.println("Hello World! "); } } public class TestDemo{ public static void main(String[] args) { A a = new B(); //向上转型 } } //最后依次输出A类和B类的构造方法
运行结果如下:
2.抽象类中可以用final声明吗?
不能,因为抽象类必须有子类,而final声明的类不能有子类。
3.抽象类能否用static声明?
外部抽象类不允许使用static声明,而内部的抽象类运行使用static声明。
用static声明的内部抽象类相当于一个外部抽象类,继承的时候使用"外部类.内部类"的形式表示类名称
abstract class A{//定义一个抽象类 static abstract class B{//static定义的内部类属于外部类 public abstract void print(); } } class C extends A.B{ public void print(){ System.out.println("**********"); } } public class TestDemo { public static void main(String[] args) { A.B ab = new C();//向上转型 ab.print(); } }
运行结果如下:
4.可以直接调用抽象类中用static声明的方法么?
任何时候,如果要执行类中的static方法的时候,都可以在没有对象的情况下直接调用,对于抽象类也一样。
abstract class A{ //定义一个抽象类 public static void print(){ System.out.println("Hello World !"); } } public class TestDemo{ public static void main(String[] args) { A.print(); } }
运行结果如下:
5.有时候由于抽象类中只需要一个特定的系统子类操作,所以可以忽略外部子类。
这样的设计在系统类库中会比较常见,目的是对用户隐藏不需要知道的子类。
abstract class A{ //定义一个抽象类 public abstract void print(); private static class B extends A{ //内部抽象类子类 public void print(){ //覆写抽象类的方法 System.out.println("Hello World !"); } } //这个方法不受实例化对象的控制 public static A getInstance(){ return new B(); } } public class TestDemo{ public static void main(String[] args) { //此时取得抽象类对象的时候完全不需要知道B类这个子类的存在 A a = A.getInstance(); a.print(); } }
运行结果如下:
(五)抽象类的应用——模板设计模式
所有的子类如果要想正常的完成操作,必须按照指定的方法进行覆写才可以,而这个时候抽象类所起的功能就是一个类定义模板的功能。
二、接口(Interface)
接口在JAVA编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。
接口定义了一种规范,规定一个类必须做什么,但是不管如何具体去做。
(一)接口与类相似点
一个接口可以有多个方法;
接口文件保存在 .java 结尾的文件中,文件名使用接口名。
接口的字节码文件保存在 .class 结尾的文件中。
接口相应的字节码文件必须在与包名称相匹配的目录结构中。
(二)接口与类的区别
接口不能实例化对象;
接口没有构造方法;
接口中的所有方法必须是抽象方法;
接口不能包含成员变量,除了static和final变量;
接口不是被类继承了,而是要被类实现;
接口支持多继承;
接口只能继承接口,不能继承类;
接口里的方法默认修饰符是public abstract;
接口里的字段全是全局变量,默认修饰符是public static final。
(三)接口特性
接口中每一个方法也是隐式抽象的,接口中的方法会被隐式的指定为 public abstract(只能是 public abstract,其他修饰符都会报错)。
接口中可以含有变量,但是接口中的变量会被隐式的指定为 public static final 变量(并且只能是 public,用 private 修饰会报编译错误)。
接口中的方法是不能在接口中实现的,只能由实现接口的类来实现接口中的方法。
(四)接口的继承
当类实现接口的时候,类要实现接口中所有的方法。否则,类必须声明为抽象的类。类使用implements关键字实现接口。在类声明中,Implements关键字放在class声明后面。
Java中类不允许多继承但接口可以。
// 文件名: Sports.java public interface Sports { public void setHomeTeam(String name); public void setVisitingTeam(String name); } // 文件名: Football.java public interface Football extends Sports { public void homeTeamScored(int points); public void visitingTeamScored(int points); public void endOfQuarter(int quarter); } // 文件名: Hockey.java public interface Hockey extends Sports { public void homeGoalScored(); public void visitingGoalScored(); public void endOfPeriod(int period); public void overtimePeriod(int ot); }
(五)接口的实现
当类实现接口的时候,类要实现接口中所有的方法。否则,类必须声明为抽象的类。
类使用implements关键字实现接口。在类声明中,Implements关键字放在class声明后面。
/* 文件名 : Animal.java */ interface Animal { public void eat(); public void travel(); } /* 文件名 : test.java */ public class MammalInt implements Animal{ public void eat(){ System.out.println("Mammal eats"); } public void travel(){ System.out.println("Mammal travels"); } public int noOfLegs(){ return 0; } public static void main(String args[]){ test m = new test(); m.eat(); m.travel(); } }
运行结果如下:
三、抽象类与接口的区别