在Java中调用的这种实例化是什么?

时间:2012-12-03 11:52:24

标签: java methods constructor override instantiation

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

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

我习惯使用new OnClickListener(arg1, arg2, ...)等构造函数初始化对象。根据我自己的经验,我在构造对象时从不覆盖方法。我只是在扩展课程时才这样做。如果有任何术语,那么在Java中调用的这种实例化是什么?在其他情况下我们应该使用它吗?

4 个答案:

答案 0 :(得分:6)

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

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

有关详细信息,请参阅here

重新。对周围阶级的引用。内部类具有对其外部类的隐式引用(如果您尝试使用XStream来序列化内部类,则可以看到此内容。它将随外部类拉出它)。如果外部类中有变量,则可以在内部引用它(假设它是final变量,请注意)

答案 1 :(得分:3)

他们被称为匿名类。

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

当您想要提供实现而无需专门声明顶级类时,它们非常有用。

他们是Java对闭包的回答。

答案 2 :(得分:2)

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

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

在Java中有一个几乎相同的结构,你几乎从未在实践中看到过:本地类。它看起来就像一个普通的类声明,但它在方法中出现,就像上面的匿名类一样。在这种情况下,类被赋予一个名称,可以在几个地方被引用和实例化,但所有这些都在声明它的方法中。

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

答案 3 :(得分: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

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