内部类的目的是什么?

60

我正在审查Java中的内部类的概念。目前为止,从我理解和应用的角度来看,Java内部类与其外部/封闭类的方法和字段有关或可访问。

我的问题:

  1. 在什么情况下应该创建或定义内部类?
  2. 内部类是否被认为是“帮助类”?
  3. 您制作内部类的指标是什么,它们的其他目的是什么?

看这个:https://dev59.com/rHE95IYBdhLWcg3wf-AF - Fritz
13个回答

53

内部类最适合于将在一个地方使用的类进行逻辑分组。例如,如果您想创建仅由封闭类使用的类,则没有必要为其创建单独的文件。相反,您可以将其添加为“内部类”。

根据Java教程

使用嵌套类的强制性原因包括以下内容:

  • 它是一种将仅在一个地方使用的类逻辑分组的方式。
  • 它增加了封装性。
  • 它可以导致更可读和可维护的代码。

这不是Javadoc,而是Java教程,它涉及嵌套类,而不是内部类,后者是一种特殊情况。 - user207421
@user207421 是的,我同意教程部分。所以,内部类不是嵌套类吗?但是,这个教程的第一行说:“Java编程语言允许您在另一个类中定义一个类。这样的类称为嵌套类”,而且如果向下滚动一点,您会看到标题为“内部类”的部分,其中显示了类似的示例。 - kosa

18
一个内部类的经典用途是在容器中实现迭代器(例如ArrayList,请查找class Itr)。容器希望向外界公开的只是一个Iterator。但是,它必须创建某个具体的该迭代器的实现,可能熟悉容器的内部情况。使用内部类隐藏了实现,同时使其保持接近容器的实现。由于是内部类(即非静态),因此它绑定到该容器的特定实例上,这使得它可以访问私有容器成员。
有一些内部类的类型-非静态嵌套类、局部类和匿名类。每种内部类的目的略有不同,因此在谈论内部类时,应指明所涉及的内部类类型。
假设您指的是非静态内部类,则使用它们的原因与使用常规类的原因相同(即抽象和将代码分成逻辑单元),但是没有理由将这种类的使用暴露给外界。当然,您也可以将嵌套类设置为public,这样您会将它们嵌套在而不是独立于外部类中,以表达它们与外部类的紧密关系。

2
非静态嵌套类也被称为内部类。它不是内部类的一种类型。 - akhil_mittal

5
作为一般规则,对象应该被设计成单一职责(高度内聚)。换句话说,任何一个被设计良好的对象,都应该执行一个单一的、连贯的任务。这被认为是面向对象设计的最佳实践。
有时候,开发人员可能会设计一个类,需要一个单独的专门的类才能工作。这个单独的专门的类可以被称为 helper 类。
如果 helper 类没有被任何其他类使用,那么它将被视为内部类的一个理想选择。
正如上面提到的 ncmathsadist 所揭示的,内部类使用的一个例子是在事件处理程序的实现中。
例如,在设计图形用户界面(GUI)时,开发人员可能创建了一个按钮,当用户按下它后,它会执行一个特定的任务。
按钮需要一个事件处理程序,它监听特定的按钮何时被按下。
在这种情况下,将按钮的事件处理程序创建为内部类将是最佳实践,因为内部类将不会在GUI类中以外的任何地方被使用。

5
  1. See the Java tutorial for the main reasons.

  2. If by "helper class" you mean something for internal use only, then no, not necessarily. You might want to do something like

    class Outer {
        private static class Inner implements InterestingInterface {
            // whatever
        }
        public InterestingInterface make_something_interesting() {
            return new Inner();
        }
    }
    

    Here, Inner is not a "helper class" in the sense that the outside world does get to see instances of it, but its implementation is entirely hidden -- the outside world only knows it gets some object that implements InterestingInterface.


所以这就是为什么他们说内部类增加了封装性的原因之一吗? - user962206
1
@user962206:是的。没有客户端需要知道他们接收到的实际上是内部类的一个实例,或者这样的类存在于“Outer”中。 - Fred Foo

3
内部类的一个用途是附加监听器。例如,假设您有一个JMenuItem。您可以像下面的代码一样使其退出应用程序:
JMenuItem quitItem = new JMenuItem("Quit");
quitItem.addActionListener(new ActionListener(){
    public void actionPerformed(ActionEvent e)
    {
        //cleanup code before exiting
        System.exit(0);
    }
});

您可能还希望一个类能够访问其外部类的状态变量,而这完全取决于该类。例如,考虑编写一个简单的颜色计算器。它可能有一个文本区域,您可以在其中输入十六进制代码。当您按下回车键时,您希望一个JPanel显示出颜色。以下是您可能要做的粗略概述。
public class ColorCalc extends JPanel implements Runnable
{
    Color displayedColor;
    JTextArea colorEnterArea;
    public ColorCalc()
    {
        displayedColor = Color.white
        colorEnterArea = new JTextArea();
    }
    public void run()
    {
        //build GUI here
    }
    public static void main(String[] args)
    {
         ColorCalc cc = new ColorCalc();
         javax.swing.SwingUtilities.invokeLater(cc);
    }
    //subservient inner class with access to outer class state variable.
    class ColorPanel extends JPanel
    {
         public void paintComponent(Graphics g)
         {
             g.setColor(displayedColor);
             g.fillRect(0,0,getWidth(), getHeight());
         } 
    }

}

2
如果您发现有足够的代码可以通过类更好地完成,因为类使我们能够通过字段和方法来指定状态和行为,并且您不希望此类在封闭类之外被使用,那么您应该使用内部类。
在这里,内部类对外界是隐藏的。 内部类可以访问封闭类的私有成员,这为我们提供了封装。
让我举个例子... 假设您想将齿轮设置为自行车,并且您有一个商业规则,例如最多只有6个齿轮。 所以您可以创建一个内部类Cycle,它将拥有一个设置齿轮的方法。 在设置齿轮之前,该方法进行一些验证,例如自行车正在运行...齿轮数小于6...
最好的例子是事件处理代码使用内部类(有时是匿名内部类)来创建事件和监听器,而无需为您的事件创建单独的事件对象和事件侦听器类。

2

这是一个样式问题。任何可以通过内部类完成的操作,也可以作为一系列外部类来完成。内部类对于轻量级或与封闭类紧密绑定的类特别有用。例如,比较器经常具备这两个特征。它需要熟悉类的实现细节,并且可能只有几行代码。它可能是一个理想的内部类候选。


1

内部类用于分组类逻辑,例如,如果您有B类,且此类仅在A类中使用,则最好将B类作为A类的内部类,这将增加代码的可读性和重用性。

愉快编程:)


1

以下是我个人笔记中的内容,供未来的访问者参考:

enter image description here enter image description here



0

从概念上讲,内部类可用于表示在没有父类型的情况下不存在的宇宙中的类型。换句话说,在允许内部类的语言中,所有类型都是“类型定义者”。然后可以将类型视为明确或隐含地定义新类型的东西。

例如,假设我们有一个宇宙,其中“食物”可以应用于任何东西。甚至是它本身。食物是我们宇宙中的基本概念。我们引入了一个名为“肉”的食物子类。如果没有这个概念,“食肉动物”就不存在。因此,我们可以(注意“可以”)定义嵌套类型“Meat.Eater”(它可以实现IEater接口),并将动物定义为不同IEaters列表的包含结构。

一旦我们将肉从宇宙中移除,食肉动物也会消失。

这种哲学思想同样适用于更抽象和技术上有用的安排,例如Memento设计模式中的备忘录、作为嵌套类定义的配置对象以及其他特定于类型的行为或结构。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接