在Java中实例化抽象类:为什么这样做?

Instantiating abstract classes in Java: Why does this work?

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
Interview : Can we instantiate abstract class?

我有一个抽象类,它定义了所有的方法(即其中不包含抽象方法),如下所示:

1
2
3
4
5
6
7
8
9
public abstract class MyAbstractClass {
  String s;
  public void setString(String s) {
    this.s = s;
  }
  public String getString() {
    return this.s;
  }
}

还有一个JUnit测试类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class TestClass {

  MyAbstractClass c;
  @Before
  public void setUp() {
    // What is happening here? And why does this work with an abstract class?
    // Instantiation? Extending the abstract class? Overwriting?
    c = new MyAbstractClass() { };
    // This will not work: (Why?)
    // c = new MyAbstractClass();
  }

  @Test
  public void test_AllMethodsAvailable() {
    // Why can I access the abstract class' methods?
    // Shouldn't they be overwritten? Or did I extend the class?
    c.setString("Test");
    assertEquals("Test", c.getString());
  }
}

我不太明白为什么对c的赋值在第一种情况下有效,而在第二种情况下无效,或者实际上在那里发生了什么(因此,为什么访问抽象类的方法在测试中有效)。

有人能给我解释一下(也可能给我指一本JavaDoc、一篇文章或一本书,解释一下为什么会这样做)吗?

为什么我可以在那里"实例化"一个抽象类?(这就是我要做的吗?)

这与内部类有关吗?


您正在用该代码创建一个匿名内部类。以这种方式创建的类是隐式扩展MyAbstractClass

因为您的abstract类没有abstract方法,所以您不必提供实现,所以这是可行的。

如果您不了解内部类,可以查看官方文档,我认为这很好。


Has it to do with inner classes?

1
 c = new MyAbstractClass() { };

当然,上面是匿名的内部类声明,您在这里不是真正实例化抽象类(您不能),而是实际创建匿名的内部类(a sub-type of MyAbstractClass)


对C的赋值之所以有效,是因为您正在用匿名非抽象类对MyAbstractClass进行子类化,C是非抽象类的一个实例。

由于抽象类中没有任何抽象方法,匿名类不必实现任何内容。


当您编写c = new MyAbstractClass() { };时,实际上创建了一个匿名类,它扩展了MyAbstractClass并且不是抽象的。由于MyAbstractClass已经定义了所有方法,因此声明是有效的。