Java 内部类的目的是什么

Java 内部类的目的是什么,java,oop,class,inner-classes,Java,Oop,Class,Inner Classes,我正在回顾java中内部类的概念。到目前为止,我所了解和应用的java内部类都有一个链接或访问其外部/封闭类的方法和字段 我的问题: 什么时候应该创建或定义内部类 内部类是否被视为“助手类” 创建内部类的指标是什么?它们的其他用途是什么?内部类最适合于对在一个位置使用的类进行逻辑分组。例如,如果您想创建只由封闭类使用的类,那么为该类创建单独的文件是没有意义的。相反,您可以将其添加为“内部类” 根据: 使用嵌套类的令人信服的原因包括: 它是一种逻辑分组类的方法,这些类只在一个应用程序中使用 地点

我正在回顾java中内部类的概念。到目前为止,我所了解和应用的java内部类都有一个链接或访问其外部/封闭类的方法和字段

我的问题:

  • 什么时候应该创建或定义内部类
  • 内部类是否被视为“助手类”

  • 创建内部类的指标是什么?它们的其他用途是什么?
  • 内部类最适合于对在一个位置使用的类进行逻辑分组。例如,如果您想创建只由封闭类使用的类,那么为该类创建单独的文件是没有意义的。相反,您可以将其添加为“内部类”

    根据:

    使用嵌套类的令人信服的原因包括:

    • 它是一种逻辑分组类的方法,这些类只在一个应用程序中使用 地点
    • 它增加了封装
    • 它可以产生更可读和可维护的代码

    内部类的一个经典用法是在容器中实现迭代器(例如,查找
    类Itr
    )。容器想要向世界其他地方公开的只是一个
    迭代器
    。然而,它必须创建迭代器的一些具体实现,可能熟悉容器的内部结构。使用内部类隐藏实现,同时使其接近容器的实现。并且是内部的(即非静态的),它被绑定到该容器的特定实例,从而允许它访问私有容器成员

    有非静态嵌套类、本地类和匿名类。每个类都有一些不同的用途,所以在询问内部类时,您应该指定您所谈论的是哪一类

    假设您指的是非静态内部类,我想说使用它们的原因与使用常规类(即抽象和将代码划分为逻辑单元)相同,但没有理由让世界其他地方都能看到类的这种使用。当然,您也可以将嵌套类公开,在这种情况下,您可以将它们嵌套而不是独立,以表示它们与外部类的紧密关系

  • 有关主要原因,请参阅

  • 如果“helper类”的意思是仅供内部使用,那么不,不一定。你可能想做一些类似的事情

    class Outer {
        private static class Inner implements InterestingInterface {
            // whatever
        }
        public InterestingInterface make_something_interesting() {
            return new Inner();
        }
    }
    
    在这里,
    internal
    并不是一个“助手类”,因为外部世界确实可以看到它的实例,但它的实现是完全隐藏的——外部世界只知道它得到了一些实现
    InterestingInterface
    的对象


  • 内部类的一个用途是附加侦听器。例如,假设您有一个
    JMenuItem
    。您可以使其退出您的应用程序,如以下代码所示:

    JMenuItem quitItem = new JMenuItem("Quit");
    quitItem.addActionListener(new ActionListener(){
        public void actionPerformed(ActionEvent e)
        {
            //cleanup code before exiting
            System.exit(0);
        }
    });
    
    // no additional classes in the package
    
    public class InterfaceTester{
    
         public static void main(String []args){
    
            // same class returns 2 instances - both compliant to 
            // either interfaces and yet different output
    
            IShark shark = OuterClass.getSharkInstance();
            System.out.println(shark.bite()); // outputs "Die fast bosedk!"
    
            IMosquito mosquito = OuterClass.getMosquitoInstance();
            System.out.println(mosquito.bite()); // outputs "Die slow bosedk!"
         }
    
    }
    
    interface IShark{
        public String bite();
    }
    
    interface IMosquito{
        public String bite();
    }
    
    class OuterClass implements IShark{
    
        // dependency of inner class on private variable
        private static String dieSlow = "Die slow bosedk!";
        private static String dieFast = "Die fast bosedk!";
    
        private static OuterClass outerInst;
        private static InnerClass innerInst;
    
        // private constructor to stop regular instantiation
        private OuterClass(){}
    
        // get a shark !
        public static IShark getSharkInstance(){
            return outerInst != null ? outerInst : new OuterClass();
        }
    
        // get a mosquito !
        public static IMosquito getMosquitoInstance(){
            return innerInst != null ? innerInst : new InnerClass();
        }
        // an implementation of bite
        public String bite(){
            return dieFast;
        }
    
        // inner class that implements the second interface
        private static class InnerClass implements IMosquito{
            // different implementation of bite
            public String bite(){
                return dieSlow;
            }
        }
    
    }
    
    您可能还希望一个类能够访问外部类状态变量,而外部类状态变量完全从属于该类。例如,考虑编写一个简单的颜色计算器。它可能有一个文本区域,您可以在其中键入十六进制代码。按enter键时,您希望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());
             } 
        }
    
    }
    

    这是一个风格问题。可以使用内部类完成的任何操作也可以作为一系列外部类来完成。内部类对于轻量级或紧密绑定到封闭类的类特别有用。例如,一个比较器经常同时处理这两个问题。它需要熟悉类的实现,并且可能只有几行。作为一个内部类,它可能是一个理想的候选者。

    如果您发现有足够的代码可以更好地由类来完成,因为类为我们提供了指定stats和 字段和方法的行为,并且您不希望该类需要在封闭类之外使用。您应该使用内部类

    在这里,内部阶级对外部世界是隐藏的。 内部类可以访问提供封装的封闭类的私有成员

    让我举个例子。。 假设您想将档位设置为循环,并且您有一个业务规则,比如最多只有6个档位。 因此,您可以创建内部类Cycle,它将有一个设置齿轮的方法。 该方法有一些验证,在设置档位之前进行检查。如循环正在运行…档位数小于6


    最好的例子是事件处理代码使用内部类(有时是匿名内部类)来创建事件和侦听器,而不为事件创建单独的事件对象和事件侦听器类。

    < P>我只认为这只是语言的一个特征。如果我们采用面向对象的方法并遵循坚实的原则,我不建议使用它

    一般来说,对象应设计为单一责任(高度内聚)。换句话说,任何设计良好的对象都应该执行一个连贯的任务。这将被视为面向对象设计的最佳实践

    然而,有时,开发人员可能会设计一个需要单独的专用类才能工作的类。这个单独的专用类可以被视为助手类

    如果helper类未被任何其他类使用,那么它将被视为主要候选类,作为内部类使用

    正如上面的ncmathsadist所引出的,内部类使用的示例将出现在事件处理程序的实现中

    例如,在设计图形用户界面(GUI)时,开发人员可能创建了一个按钮,该按钮在用户按下后执行特定的任务

    该按钮需要一个事件处理程序
    // no additional classes in the package
    
    public class InterfaceTester{
    
         public static void main(String []args){
    
            // same class returns 2 instances - both compliant to 
            // either interfaces and yet different output
    
            IShark shark = OuterClass.getSharkInstance();
            System.out.println(shark.bite()); // outputs "Die fast bosedk!"
    
            IMosquito mosquito = OuterClass.getMosquitoInstance();
            System.out.println(mosquito.bite()); // outputs "Die slow bosedk!"
         }
    
    }
    
    interface IShark{
        public String bite();
    }
    
    interface IMosquito{
        public String bite();
    }
    
    class OuterClass implements IShark{
    
        // dependency of inner class on private variable
        private static String dieSlow = "Die slow bosedk!";
        private static String dieFast = "Die fast bosedk!";
    
        private static OuterClass outerInst;
        private static InnerClass innerInst;
    
        // private constructor to stop regular instantiation
        private OuterClass(){}
    
        // get a shark !
        public static IShark getSharkInstance(){
            return outerInst != null ? outerInst : new OuterClass();
        }
    
        // get a mosquito !
        public static IMosquito getMosquitoInstance(){
            return innerInst != null ? innerInst : new InnerClass();
        }
        // an implementation of bite
        public String bite(){
            return dieFast;
        }
    
        // inner class that implements the second interface
        private static class InnerClass implements IMosquito{
            // different implementation of bite
            public String bite(){
                return dieSlow;
            }
        }
    
    }