如果一个抽象class不能被实例化,为什么下面的可能呢?

If an abstract class can't be instantiated, why is the following possible?

在下面的代码中,一个 Graphics 对象被传递到下面的 paintComponent 方法中,然后它被转换成一个 Graphics2D 对象。 Graphics 不是抽象的 class 那为什么下面的可能呢?

 public void paintComponent(Graphics comp) {
 Graphics2D comp2D = (Graphics2D) comp;
 Font font = new Font("Comic Sans", Font.BOLD, 15);
 comp2D.setFont(font);
 comp2D.drawString("Potrzebie!", 5, 50);
}

A class 是抽象的只是意味着你不能直接创建这样的 class。一旦你有了这样一个 class,你就可以转换它使它看起来像它的任何子classes。换句话说,所有"abstract"意味着你不能做:

SomeAbstractClass obj = new SomeAbstractClass(...);

您可以引用 Graphics2D 对象,就像在您的示例中一样,但是如果您要求 Java 告诉您对象的真实类型,它实际上永远不会是 Graphics2D 对象。从这段代码中,您也不能确定所讨论对象的真实类型是 Graphics 对象。这可能又是对真实对象的子 class 的引用,例如 MyGraphicsObject 或类似的东西。

这就是多态性的全部意义和威力。一旦你创建了一个对象,它的行为就像它的任何子classes 一样,并且可以通过向上转换将它视为任何这些子classes 的纯实例。

这里有一些代码指出了向上转型的对象的标识会发生什么:

abstract class Abstract {
    public void whatAmI() {
        System.out.println("I'm Abstract");
    }
}

class Concrete extends Abstract {
    @Override
    public void whatAmI() {
        System.out.println("I'm Concrete");
    }
}

public class X {

    public static void main(String[] args) {

        // This won't compile.  That's what it means for "Abstract" to be abstract.
        // Abstract abs = new Abstract();

        // You can create a Concrete, and then upcast it to an Abstract reference...
        Concrete concrete = new Concrete();
        Abstract abs = (Abstract)concrete;

        // But it's stll really a Concrete
        System.out.println(abs.getClass().getName());

        // And it will still act like a Concrete if Concrete has overridden one of Abstract's methods.
        abs.whatAmI();
    }
}

结果:

org.littleshoot.proxy.inlet.Concrete
I'm Concrete

请注意,如果您询问 Java 对象的类型,即使您已通过抽象引用询问对象的类型,它仍然是具体的。另请注意,如果您在抽象 class 上调用已在混凝土中覆盖的方法,则将调用混凝土的版本。

仅仅因为 class 无法实例化并不意味着您无法获得它的实例。

在您的示例中,您所做的只是将其转换为图形层次结构中的另一个 class。

这是一个例子。


    public class AbstractDemo {

       public static void main(String[] args) {
          Concrete c = new Concrete();
          AClass a = (AClass) c;
          a.me();
       }

    }

    abstract class AClass {
       public void me() {
          System.out.println("Abstract parent");
       }
    }

    class Concrete extends AClass {

    }