【问题标题】:What is this kind of instantiation called in Java?在 Java 中这种实例化是什么?
【发布时间】:2012-11-20 21:14:56
【问题描述】:

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

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

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

【问题讨论】:

  • Java 中的名称是Anonymous Classes。现在您可以继续研究这个主题了。
  • OnClickListener 绝对是匿名实例化

标签: java methods constructor overriding instantiation


【解决方案1】:

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

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

请参阅here 了解更多信息。

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

【讨论】:

  • 我不确定“引用其周围的类”是什么意思。您能否说出一个可以使用这种参考的场景?
【解决方案2】:

它们被称为匿名类。

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

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

它们是 Java 对闭包的回答。

【讨论】:

    【解决方案3】:
    new OnClickListener()
    {
      @Override
      public void onClick(View v)
      {
        Thread.sleep(100);
      }
    }
    

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

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

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

    【讨论】:

      【解决方案4】:

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

      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
      

      您可以覆盖方法以添加额外的功能,并在以后在运行时使用此类。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-08
        相关资源
        最近更新 更多