1.抽象类的定义
普通类可以直接产生实例化对象,并且在普通类之中可以包含有构造方法、普通方法、static方法、常量、变量等内容。而所谓抽象类,就是指在普通类的结构里面增加抽象方法的组成部分。
所有的普通方法都会有一个“{ }”,这个表示方法体,有方法体的方法一定可以被对象直接使
用,而抽象方法指的是没有方法体的方法,同时还必须使用abstract关键字进行定义。
拥有抽象方法的类一定属于抽象类,抽象类使用abstract声明。
范例:定义一个抽象类
abstract class A{
public void fun(){//普通方法
System.out.println("有方法体的普通方法!");
}
public abstract void print();//此方法没有方法体,有abstract关键字,表示抽象方法。
}
范例:抽象类产生对象??
public class TestDemo{
public static void main(String args[]){
A a = new A();//A是抽象的,无法实例化
a.fun();
a.print();
}
}
这个时候发现程序报错,不能够对A对象实例化。之所以不能够实例化,因为里面有抽象方法,
对象不能够调用没有方法体的方法,也就无从谈实例化对象。
对于抽象类的使用原则:·抽象类必须有子类;
·抽象类的子类,不能是抽象类,必须要覆写抽象类之中的全部抽象方法;
·抽象类的对象实例化需要依靠子类完成,采用向上转型的方式处理。
范例:正确使用抽象类
class B extends A{
public void print(){
System.out.println("Hello World!");
}
}
public class TestDemo{
public static void main(String args[]){
A a = new B();//向上转型
a.fun();
a.print();// 被子类覆写的方法
}
}
2. 抽象类的相关限制
· 抽象类里面由于会存在一些属性,那么在抽象类之中一定会存在构造方法。目的:为属性初始化。并且子类对象实例化的时候,依然满足先执行父类构造,再调用子类构造。
· 抽象类不能使用final定义,因为抽象类必须有子类,而final定义的类不能够有子类。
· 外部抽象类不允许使用static声明,而内部的抽象类允许使用static声明,使用static声明
的内部抽象类就相当于外部抽象类。继承的时候,使用“外部类.内部类”的形式表示类名称。
· 任何情况下,调用类中的static方法的时候,都可以在没有对象的时候直接调用,对于抽象
类也是一样。
· 有些时候,由于抽象类只需要一个特定的系统子类操作,所以可以忽略掉外部子类。
范例:static声明内部抽象类
abstract class A{
static abstract class B{
public abstract void print();
}
}
class X extends A.B{
public void print(){
System.out.println("static声明内部抽象类");
}
}
public class TestDemo {
public static void main(String args[]){
A.B ab = new X(); //向上转型
ab.print();
}
}
范例:忽略抽象类的外部子类
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();
}
}
请分析下面代码的结果:
abstract class A{public A(){ // 2. 执行父类构造
this.print(); // 3. 调用print()
}
public abstract void print();
}
class B extends A{
private int num = 100;
public B(int num){ // 5.执行子类构造 num = 30;
this.num = num;
}
public void print(){ // 4. 调用覆写的print(),此时num未初始化,num = 0
System.out.println("num = "+ num);
}
}
public class TestDemo{
public static void main(String args[]){
new B(30).print(); // 1. 执行构造
}
}
解决思路:在任何一个类的构造完成之前,所有属性的内容都是其对应数据的默认值,而子类对构造执行之前,一定先执行父类构造。