3

这对于 Java 来说可能是一个非常基本的问题,但我就是想不起来,也不知道如何在线搜索。

button.setOnClickListener(new OnClickListener()
{
  @Override
   public void onClick(View v)
   {
     Thread.sleep(100);
   }
}

我习惯于使用诸如new OnClickListener(arg1, arg2, ...). 以我自己的经验,我在构造对象时从未覆盖过方法。我只在扩展课程时才这样做。如果有任何术语,这种实例化在 Java 中称为什么?在其他什么情况下我们应该使用它?

4

4 回答 4

6

那是一个匿名类。它是OnClickListener接口的一个实现,但该实现是未命名的。它写起来很简洁,实现在调用上下文中是可见的(通常对可读性很有用),但由于它是就地实现,你不能在其他地方使用它。

另请注意,它是一个内部类,因此具有对其周围类的引用。

请参阅此处了解更多信息。

关于。对周围类的引用。内部类具有对其外部类的隐式引用(如果您尝试使用 XStream 等对内部类进行序列化,您会看到这一点。它会拉动外部类)。如果您在外部类中有一个变量,您可以在内部类中引用它(前提是它是一个final变量,请注意)

于 2012-12-03T11:53:41.027 回答
3

它们被称为匿名类。

从技术上讲,它们是被实例化的类的子类,并提供重写的方法实现。

当您想要提供一个实现而不必专门声明顶级类时,它们很有用。

它们是 Java 对闭包的回答。

于 2012-12-03T11:53:23.427 回答
2
new OnClickListener()
{
  @Override
  public void onClick(View v)
  {
    Thread.sleep(100);
  }
}

从语法和语义的角度来看,这个构造是实例化类声明的混合。同时,您指定OnClickListener要调用的构造函数(为此,假定接口具有默认构造函数)并提供属于您要声明的新子类的类主体。你没有给子类命名,这就是为什么这个构造被称为“匿名类”。匿名类实例化与声明紧密耦合,您不能从代码中的任何其他点实例化该类,除非它被声明。

在 Java 中有一个几乎相同的构造,你几乎不会在实践中看到它:一个本地类。它看起来就像一个普通的类声明,但它发生在一个方法内部,就像上面的匿名类一样。在这种情况下,该类被赋予了一个名称,并且可以在多个地方引用和实例化,但它们都在声明它的方法中。

在这两种情况下,您都可以获得任何其他类都无法使用的特殊功能,即使用方法中声明的局部变量的能力。起初这很奇怪,因为当方法完成时局部变量消失了,但是对局部类实例的引用继续存在。这就是为什么这些类被称为“闭包”的原因:据说它们“关闭”了它们的本地环境。他们有点“提升”变量声明并将它们保留为它们的实例变量。

于 2012-12-03T11:58:11.833 回答
1

只是举一个如何使用它的例子......

public class TestClass {
    public static void main(String args[]) {
        OutOfTheMain ootm = new OutOfTheMain();
    }
}

public interface SuperInner {
    String words = "hello";
    String getWords();
}

public class OutOfTheMain {
    OutOfTheMain() {
        testInnerStuff(new SuperInner() {
            @Override
            public String getWords() {
                return words + " world";
            }
        });
    }

    private void testInnerStuff(SuperInner sinner) {
        System.out.println(sinner.getWords());
    }
}

运行时,这将打印...

hello world

您可以覆盖方法以添加其他功能,并稍后在运行时使用此类。

于 2012-12-03T12:20:14.693 回答