如何在实践中使用内部类

Bir*_*088 6 java anonymous-inner-class inner-classes

为什么会有人使用inner class?使用local class或可以实现相同的功能subclass.

一个例子也将被赞赏.

Zie*_*mdi 11

内部类可用于许多功能案例.它们具有两个优点:

  1. 内部类可以看到外部类的字段(如果它不是静态的).这意味着您不必处理外部类字段,就好像它们来自外部类.这意味着您的内部类需要外部类的实例才能工作.如果您的类是静态的,那么它就像一个独立的类.
  2. 内部类与其拥有的类紧密相关.所以,即使它是静态的,你知道它的名字与它所拥有的类有关.

有了这个说,你可以理解内部类必须在事物属于一起的地方使用.

所以最可能的情况是你不需要外部类之外的内部类.例如:

class ScreenCapture {
  class CaptureButtonListener implements ClickListener {
     public void onClick( ClickEvent click ) {
       //..capture
       pressCount++;
     }
  }

  Button button = new Button("capture");
  int pressCount = 0;

  void addListeners() {
    button.addClickListener( new CaptureButtonListener() );
  }
}
Run Code Online (Sandbox Code Playgroud)

如你看到的:

  • 你永远不会需要ScreenCapture之外的CaptureButtonListener.因此最好隐藏它(甚至将其声明为私有或受保护).
  • 内部类正在访问不属于它的字段:pressCount.这是可能的,因为它的实例与ScreenCapture实例绑定:您无法new CaptureButtonListener()在静态方法中创建:您必须在实例方法中使用它.

另一方面,静态内部类仅用于组织目的(两个类都相关).我将使用静态内部类调整前面的示例:

public class ScreenCapture {
  public static class CaptureButtonListener implements ClickListener {
    protected ScreenCapture controller;
    public CaptureButtonListener( ScreenCapture controller ) {
      this.controller = controller;
    }

     public void onClick( ClickEvent click ) {
       //..capture
       controller.pressCount++;
     }
  }

  Button button = new Button("capture");
  int pressCount = 0;

  public void captureRequested() {
    //do capture...
    pressCount++;
  }

  void addListeners() {
    button.addClickListener( new CaptureButtonListener(this) );
  }
}
Run Code Online (Sandbox Code Playgroud)

请注意,在这种情况下:

  • 无法从内部类访问变量pressCount:您必须指定它所属的实例.
  • 您可以从外部实例化CaptureButtonListener,但您可以直接从其名称中看到:new ScreenCapture.CaptureButtonListener( screenCaptureInstance )它与ScreenCapture类相关(这提高了代码的可读性)

现在您可能想知道为什么要创建一个无法访问其所有者字段的内部类?你是对的:在我们的情况下这不是很明智,因为你不得不将ScreenCapture的一个实例传递给构造函数(因此你不能将它与除ScreenCapture之外的任何其他类一起使用).这只是为了证明这种差异.

以下示例将给出前一个例子:

您可以将侦听器声明为ScreenCapture内的公共静态接口

class ScreenCapture {
  public static interface class CaptureRequestListener {
     public void captureRequested( ClickEvent click );
  }
}
Run Code Online (Sandbox Code Playgroud)

通过这种方式,您可以传递"如何处理捕获请求"的ScreenCapture实现

同样,接口的实现将知道他们正在实现ScreenCapture特有的东西,因为它们将实现

public class MyImpl implements ScreenCapture.CaptureRequestListener {
  public void captureRequested( ClickEvent click ) {
    // I will count requests instead
  }
}
Run Code Online (Sandbox Code Playgroud)

因此,您的代码比在每个文件组织的单独类中更清晰.

您还可以拥有一个基本处理类(作为内部类的常见任务的抽象实现)

我希望一切都很清楚:-)最好的问候,Zied