抽象类可不可以实例化?

从广义上来讲,抽象类可以被实例化,从狭义上讲,抽象类不能被实例化,接下来我们将从这两个方面展开讨论.

1.普通类的实例化

我们首先创建一个普通类Person,

public class Person{
    public void study(){
        System.out.println("我爱学习");
    }
}

然后再创建一个测试类Test,用于测试Person的实例化.

public class Test{
    public static void main(String[] args){
        Person person = new Person();
        person.study();
    }
}

运行程序,成功地输出了”我爱学习”,说明成功的调用了Person中的方法study(),person即为类Person的实力化对象.

2.抽象类的实例化
既然普通类可以通过new关键字实例化对象,那么抽象类是否可以呢?
我们首先创建一个抽象类AbstractPerson

public abstract class AbstractPerson{
    public abstract void study();
}

然后在测试类中测试实例化AbusractPerson

public class Test{
    public static void main(String[] args){
        Person person = new Person();
        person.study();

        AbstractPerson aPerson = new AbstractPerson();//Error
    }
}

当我们模仿普通类创建AbstractPerson的实例化对象时,编译器给我们来了个报错,为什么会报错呢?

java 抽象类根据不同类型走不同子类的方法 抽象类不能实例化_实例化


告诉我们AbstractPerson是抽象类,不能被实例化,我们就这样放弃了吗?还有没有别的办法?

当然有!我们可以使用匿名内部类将抽象类中的抽象方法实现,这样不就可以对其实例化了.

public class Test {
    public static void main(String[] args){
        Person person = new Person();
        person.study();

        AbstractPerson aPerson = new AbstractPerson(){

            @Override
            public void study() {
                System.out.println("我在抽象地学习");
            }
        };
        aPerson.study();
    }
}

运行程序得到以下输出
我爱学习
我在抽象地学习

类比普通类的实例化,我们得到了相同的效果,是不是说抽象类可以被实例化了?从广义上来说,我们完成了对抽象类的实例化,但深入了解的话是不是这样呢?

3.抽象类实例化的剖析

在IDEA中,可以使用ctrl+H可以查看类的关系,我们在AbstractPerson类中使用此快捷键可以看到下图:

java 抽象类根据不同类型走不同子类的方法 抽象类不能实例化_抽象类_02


可以看到在AbstractPerson类下面多了一个类,可是我们的列表中并没有这个类,这个其实就是我们实现抽象方法的时候所建立的匿名内部类,可见我们创建的实例化对象其实是这个匿名内部类的,并不是AbstractPerson抽象类的实例化对象.

如何佐证这一点呢,我们使用equal方法来判断我们得到的实例化对象到底属不属于AbstractPerson类.

在Test类中补充如下代码

public class Test {
    public static void main(String[] args){
        Person person = new Person();
        person.study();

        AbstractPerson aPerson = new AbstractPerson(){

            @Override
            public void study() {
                System.out.println("我在抽象地学习");
            }
        };
        aPerson.study();
        System.out.println(
                aPerson.getClass().equals(AbstractPerson.class));
        //判断aPerson所属的类与AbstractPerson是否相同,若相同返回true
    }
}

运行 返回false 说明aPerson并不是AbstractPerson的实例化对象

总结
我们通过匿名内部类成功的创建了可以调用AbstractPerson中方法的实例化对象,但它并不属于AbstractPerson,而是属于我们创建的匿名内部类,实际上调用的是匿名内部类中的方法,从广义上讲,我们通过匿名内部类成功实例化了AbstractPerson,但从狭义上讲,我们实例化的只是那个匿名内部类.
关于抽象类能否被实例化一致就有两种声音,我们不应该纠结于这个问题的结果,应该通过问题看到抽象类和匿名内部类之间的关系,再具体运用的时候,我们可以通过匿名内部类快速创建一个指向抽象类的对象,而不用再创建一个类实现其方法,同时我们也应该理解所创建对象真正的归属.