1、使用abstract类的动机:可以参考 Cay?S.?Horstmann, Gary?Cornel 写的书《Core Java? 2 Volume I - Fundamentals, Seventh
Edition 》(顺便罗嗦一下,该书是偶见过最好的Java入门书) ?Classes, Superclasses, and
Subclasses ?一节,定义一个abstract class的格式是:修饰符(public, private, etc)+abstract+类名
或者 abstract + 修饰符 + 类名。
2、如果一个类至少存在一个抽象方法(abstract method),则它自身必须声明成一个抽象类。但一个类可以被声明成一个抽象类即使它没有任何抽象方法。声明一个abstract method的格式是:修饰符(public, private, etc)+abstract+返回类型 + 方法名 或者 abstract + 修饰符 + 返回类型 + 方法名。
3、一个抽象类可以有数据域和非抽象方法(concrete data and concrete methods)。
4、当一个子类继承某个抽象类时,它可以有两个选择:
??? (1)??? 部分实现或完全不实现父类的所有抽象方法,但此时子类必须声明为抽象类。
??? (2)??? 实现父类所有的抽象方法,此时之类不比声明为抽象类。
5、抽象类不能被实例化(be instantiated),但可以实例化非抽象子类(concrete subclass)。
?? 可以声明抽象类变量,但该变量必须指向一个非抽象子类.看下面一个例子:
6、摘自《Core Java 2》的一个例子:

PersonTest.java
/**
???@version?1.01?2004-02-21
???@author?Cay?Horstmann
*/
import?java.text.*;
import?java.util.*;
public?class?PersonTest
{??
???public?static?void?main(String[]?args)
???{??
??????Person[]?people?=?new?Person[2];
??????//?fill?the?people?array?with?Student?and?Employee?objects
??????people[0]?=?new?Employee("Harry?Hacker",?50000,?1989,?10,?1);
??????people[1]?=?new?Student("Maria?Morris",?"computer?science");
??????//?print?out?names?and?descriptions?of?all?Person?objects
??????for?(Person?p?:?people)
?????????System.out.println(p.getName()?+?",?"?+?p.getDescription());
???}
}
abstract?class?Person
{??
???public?Person(String?n)
???{??
??????name?=?n;
???}
???public?abstract?String?getDescription();
???public?String?getName()
???{??
??????return?name;
???}
???private?String?name;
}
class?Employee?extends?Person
{??
???public?Employee(String?n,?double?s,
??????int?year,?int?month,?int?day)
???{??
??????super(n);
??????salary?=?s;
??????GregorianCalendar?calendar?=?new?GregorianCalendar(year,?month?-?1,?day);
??????hireDay?=?calendar.getTime();
???}
???public?double?getSalary()
???{??
??????return?salary;
???}
???public?Date?getHireDay()
???{??
??????return?hireDay;
???}
???public?String?getDescription()
???{??
??????return?String.format("an?employee?with?a?salary?of?$%.2f",?salary);
???}
???public?void?raiseSalary(double?byPercent)
???{??
??????double?raise?=?salary?*?byPercent?/?100;
??????salary?+=?raise;
???}
???private?double?salary;
???private?Date?hireDay;
}
class?Student?extends?Person
{??
???/**
??????@param?n?the?student's?name
??????@param?m?the?student's?major
???*/
???public?Student(String?n,?String?m)
???{??
??????//?pass?n?to?superclass?constructor
??????super(n);
??????major?=?m;
???}
???public?String?getDescription()
???{??
??????return?"a?student?majoring?in?"?+?major;
???}
???private?String?major;
}
2、如果一个类至少存在一个抽象方法(abstract method),则它自身必须声明成一个抽象类。但一个类可以被声明成一个抽象类即使它没有任何抽象方法。声明一个abstract method的格式是:修饰符(public, private, etc)+abstract+返回类型 + 方法名 或者 abstract + 修饰符 + 返回类型 + 方法名。
3、一个抽象类可以有数据域和非抽象方法(concrete data and concrete methods)。
4、当一个子类继承某个抽象类时,它可以有两个选择:
??? (1)??? 部分实现或完全不实现父类的所有抽象方法,但此时子类必须声明为抽象类。
??? (2)??? 实现父类所有的抽象方法,此时之类不比声明为抽象类。
5、抽象类不能被实例化(be instantiated),但可以实例化非抽象子类(concrete subclass)。
?? 可以声明抽象类变量,但该变量必须指向一个非抽象子类.看下面一个例子:
???1.??Person?[]?people?=?new?Person[2];????
???2.?people[0]?=?new?Employee(
);????
???3.?people[1]?=?new?Student(
);??
???4.?for?(Person?p?:?people)??
???5.????System.out.println(p.getName()?+?","?+?p.getDescription());??
注意代码中的一个调用:p.getDescription().可能有人会担心这里调用了一个没定义的方法。但是, 由于不能构造抽象类Person的对象,所以p永远不会调动Person对象,而是只会调用诸如Employee或Student这样的具体子类方法。注意,如果没有定义Person中抽象方法getDescription()但是通过p调用getDescription()则会产生编译错误,编译器只允许调用在类中声明的方法。???2.?people[0]?=?new?Employee(

???3.?people[1]?=?new?Student(

???4.?for?(Person?p?:?people)??
???5.????System.out.println(p.getName()?+?","?+?p.getDescription());??
6、摘自《Core Java 2》的一个例子:


/**
???@version?1.01?2004-02-21
???@author?Cay?Horstmann
*/
import?java.text.*;
import?java.util.*;
public?class?PersonTest
{??
???public?static?void?main(String[]?args)
???{??
??????Person[]?people?=?new?Person[2];
??????//?fill?the?people?array?with?Student?and?Employee?objects
??????people[0]?=?new?Employee("Harry?Hacker",?50000,?1989,?10,?1);
??????people[1]?=?new?Student("Maria?Morris",?"computer?science");
??????//?print?out?names?and?descriptions?of?all?Person?objects
??????for?(Person?p?:?people)
?????????System.out.println(p.getName()?+?",?"?+?p.getDescription());
???}
}
abstract?class?Person
{??
???public?Person(String?n)
???{??
??????name?=?n;
???}
???public?abstract?String?getDescription();
???public?String?getName()
???{??
??????return?name;
???}
???private?String?name;
}
class?Employee?extends?Person
{??
???public?Employee(String?n,?double?s,
??????int?year,?int?month,?int?day)
???{??
??????super(n);
??????salary?=?s;
??????GregorianCalendar?calendar?=?new?GregorianCalendar(year,?month?-?1,?day);
??????hireDay?=?calendar.getTime();
???}
???public?double?getSalary()
???{??
??????return?salary;
???}
???public?Date?getHireDay()
???{??
??????return?hireDay;
???}
???public?String?getDescription()
???{??
??????return?String.format("an?employee?with?a?salary?of?$%.2f",?salary);
???}
???public?void?raiseSalary(double?byPercent)
???{??
??????double?raise?=?salary?*?byPercent?/?100;
??????salary?+=?raise;
???}
???private?double?salary;
???private?Date?hireDay;
}
class?Student?extends?Person
{??
???/**
??????@param?n?the?student's?name
??????@param?m?the?student's?major
???*/
???public?Student(String?n,?String?m)
???{??
??????//?pass?n?to?superclass?constructor
??????super(n);
??????major?=?m;
???}
???public?String?getDescription()
???{??
??????return?"a?student?majoring?in?"?+?major;
???}
???private?String?major;
}