抽象类
在Java中可以创建一种类专门用来做父类,这种类称为“抽象类”。抽象类实际上也是一个类,只是与之前的普通类相比,内部新增了抽象方法。
1、抽象方法
抽象方法是只声明而未实现的方法。
例:
void f(); // 只有声明,没有实现。
2、抽象类的定义与使用
(1)抽象类和抽象方法都必须用abstract关键字来修饰;
(2)抽象类不能直接实例化,也就是不能直接用new关键字去产生对象;
(3)抽象类定义时抽象方法只需声明,而不需实现;
(4)含有抽象方法的类必须被声明为抽象类,抽象类的子类必须覆写所有的抽象方法后才能被实例化,否则这个子类还是个抽象类。
(5)抽象类可以定义普通方法,普通方法可以有方法体。
例:
public abstract class Book {
private String bookName = "《Java编程思想》"; // 定义属性:书名
public void printName() { // 定义普通方法:打印书名
System.out.println(bookName);
}
public abstract void f(); // 定义一个抽象方法
public static void main(String[] args) {
Book b = new Book(); // 错误,抽象类无法实例化对象
}
}
【结果】
其实,抽象类也就是比普通类多了一些抽象方法而已。 如果说一个类的对象可以被实例化,那么就表示这个对象可以调用类中的属性和方法,但是抽象类中存在抽象方法,而抽象方法没有方法体,没有方法体的方法自然无法使用了。
(6)抽象类必须有子类,子类使用extends继承抽象类,一个子类只能够继承一个抽象类;子类(如果不是抽象类),则必须要全部覆写抽象类中的全部抽象方法;如果想要实例化抽象类的对象,则可以使用子类进行对象的向上转型来完成。
例:
abstract class Person //定义一抽象类Person
{
String name;
int age;
String occupation;
public abstract String talk();//声明一个抽象方法talk()
}
class Student extends Person //Student类继承自Person类
{
public Student(String name,int age,String occupation)
{
this.name=name;
this.age=age;
this.occupation=occupation;
}
public String talk() //覆写抽象方法talk()
{
return"学生——>姓名:"+this.name+",年龄:"+this.age+",职业:"+this.occupation+"!";
}
}
public class AbstractClassDemo
{
public static void main(String[] args)
{
Student s=new Student("张三",20,"学生"); //创建Student类对象
Person p = new Student("王五",22,"学生"); // 向上转型为Person类
System.out.println(p.talk()); //调用被覆写过的方法
System.out.println(s.talk()); //调用被覆写过的方法
}
}
【结果】
(7)抽象类中可以有构造方法。
与一般类相同,在抽象类中也可以拥有构造方法,但是这些构造方法必须在子类中被调用,并且子类实例化对象的时候依然满足类继承的关系,先默认调用父类的构造方法,而后再调用子类的构造方法,毕竟抽象类之中还是存在属性的,只不过这个抽象方法无法直接被外部实例化对象的时候所使用。
abstract class Person //定义一抽象类Person
{
String name;
int age;
String occupation;
public Person(String name, int age, String occupation) { // 定义一构造方法
this.name=name;
this.age=age;
this.occupation=occupation;
}
public abstract String talk();//声明一个抽象方法talk()
}
class Student extends Person //Student类继承自Person类
{
public Student(String name,int age,String occupation)
{
super(name, age, occupation); // 子类必须先调用抽象类的构造方法
this.name=name;
this.age=age;
this.occupation=occupation;
}
public String talk() //覆写抽象方法talk()
{
return"学生——>姓名:"+this.name+",年龄:"+this.age+",职业:"+this.occupation+"!";
}
}
public class AbstractClassDemo
{
public static void main(String[] args)
{
Student s=new Student("张三",20,"学生"); //创建Student类对象s
Person p = new Student("王五",22,"学生"); // 向上转型为Person类
System.out.println(p.talk()); //调用被覆写过的方法
System.out.println(s.talk()); //调用被覆写过的方法
}
}
【结果】
综上可知,抽象类也可以像普通类一样,有构造方法、一般方法和属性,更重要的是还可以有一些抽象方法,需要子类去实现,而且在抽象类中声明构造方法后,在子类中必须明确调用。
(8)抽象类不能够用final定义。
使用final定义的类不能有子类,而抽象类使用的时候必须有子类,这是一个矛盾的问题,所以抽象类上不能出现final定义。
(9)在外部抽象类上无法使用static声明,但是内部抽象类却可以使用static定义,使用static定义的内部抽象类就表示一个外部类。
例:
abstract class Book { // 外部抽象类无法用static声明
public abstract void print(); // 抽象方法
static abstract class CD { // 静态内部抽象类,相当于一个外部类
public abstract void get(); // 抽象方法
}
}
class JavaCD extends Book.CD { // 继承静态内部抽象类
@Override
public void get() { // 重写静态内部抽象类的抽象方法
System.out.println("Java学习!");
}
}
public class StaticInnerAbstractClass {
public static void main(String[] args) {
Book.CD cd = new JavaCD(); // 实例化对象,向上转型为父类CD
cd.get();
}
}
【结果】
(10)抽象类之中可以没有抽象方法,但即便没有抽象方法的抽象类也不能够直接通过关键字new实例化。
例:
abstract class Book { // 没有抽象方法的抽象类
}
public class StaticInnerAbstractClass {
public static void main(String[] args) {
Book b = new Book(); // 错误,无法实例化
}
}
【结果】