内在阶级的目的是什么?

时间:2013-11-26 03:56:40

标签: java inner-classes

我正在阅读界面和类中的内部类。我无法理解真正的用途。但是我不想在这篇文章中讨论关于接口内部内部类的任何内容。

到目前为止,我已将内部类用作回调。我也可以在某个地方宣布课程。

假设我有一个学生列表,我想按ID对它们进行排序。我必须实现Comparator接口并将其作为Collections的排序方法的参数提供。

public class StudentList {

    public static void main(String[] args) {

        List<Student> students = new ArrayList<Student>();

        Student student = new Student();
        student.setId(1);
        student.setName("Krishna");
        students.add(student);

        student = new Student();
        student.setId(2);
        student.setName("Chaitanya");
        students.add(student);

        Collections.sort(students, new StudentList().new MyComparator());
    }

    public class MyComparator implements Comparator<Student> {

        @Override
        public int compare(Student o1, Student o2) {

            if (o1.getId() < o2.getId()) {
                return 1;
            } else if (o1.getId() > o2.getId()) {
                return -1;
            } else {
                return 0;
            }
        }

    }

}

我也可以这样做

public class StudentList {

    public static void main(String[] args) {

        List<Student> students = new ArrayList<Student>();

        Student student = new Student();
        student.setId(1);
        student.setName("Krishna");
        students.add(student);

        student = new Student();
        student.setId(2);
        student.setName("Chaitanya");
        students.add(student);

        Collections.sort(students, new MyComparator());
    }

}

class MyComparator implements Comparator<Student> {

    @Override
    public int compare(Student o1, Student o2) {

        if (o1.getId() < o2.getId()) {
            return 1;
        } else if (o1.getId() > o2.getId()) {
            return -1;
        } else {
            return 0;
        }
    }

}

我不认为上面例子中的内部类会增加任何重要的重要性,除非它被声明为私有类。当我将其声明为私有时,只有封闭类可以使用它。这意味着该类与封闭类强烈绑定,我看到了这样的优点。

任何人都可以向我解释在应用程序中使用/编写内部类的真正重要性/意义。

8 个答案:

答案 0 :(得分:4)

如果您需要与您合作的课程特定的内容,您应该是内部课程。可以在此处找到内部类的一个很好的示例:java.awt.geom.Ellipse2D和相应的Ellipse2D.DoubleEllipse2D.FloatEllipse2D source code)。您可以将这些类放在一个包中,但它们作为嵌套类更有意义。它们直接对应Ellipse2D,在其他地方没用;而且,它们是嵌套的这一事实提高了使用它们的代码的可读性。另一方面,如果内部类在更一般的情况下非常有用,那么通常更好地概括它并创建常规类。

此外,内部类可以直接访问外部类中的变量。这意味着可以使用内部类来更改外部类。仍然可以在任一类之外使用它的实例。为了说明我的意思:

public class Example {
    public static void main(String[] args) {
        Foo foo = new Foo();
        Foo.Bar bar = foo.getBar(); //note, cannot call new Foo.Bar(); as Bar is dependent on Foo
        for (int i = 0; i < 50; i++){
            System.out.println(bar.get());
        }
    }
}
class Foo {
    int val;
    Bar b;

    public Foo(){
        b = new Bar();
    }
    public Bar getBar(){
        return b;
    }
    public class Bar{
        public Bar(){
            val++;
        }
        public int get(){
            return val++;
        }
    }
}

内部类的另一种可能用途是为真正想要的内部类创建类似包装类的东西,尤其适用于递归类。这用于实现LinkedList。有一段时间,我实现了这样一个列表,没有意识到之前已经做过任何类似的事情。我们的想法是,您拥有LinkedList类,并且其中包含Node类(其中每个节点仅指向下一个/上一个节点并保留单个值)。这样做可以简化代码。但是,Node类在LinkedList外部没有任何意义,因为它会是什么类型的“节点”?因此它应该是一个内部类。

答案 1 :(得分:1)

有些课程本身并没有多大意义 - 他们只是制作 在另一个班级的背景下感觉。内部课程很有帮助 定义这种关系 - 他们允许开发人员 更明确地表达高度内聚类之间的关系。

see more

作为示例考虑图中的节点。节点有一个对等列表 它可以达到自己的节点。定义Peer类是有意义的 作为Node的内部类。例如:

public class Node
{
private String name;
private List peers = new ArrayList();

private Node( String name )
{
this.name = name;
}

/**
* Represents a peer node that is reachable from this node
*/
class Peer
{
private Node node;
private int distance;
}
}

答案 2 :(得分:1)

我看到了两个优点。我没有太多地使用它们,所以只有我的观察。

  1. 如果内部类很小,可能更容易定义为内部而不是为它创建单独的文件。这对于已经有太多文件的大型项目的可管理性有帮助。

  2. 其次,如果内部类只能在它的父类的上下文中使用,那么将它定义为内部类会给它包含父类的命名空间。

    public class FileProcessor {
     public class Output {
       //will be namespaced as FileProcessor.Output, more readable.
     }
    }
    
  3. 回答Inner Class. What is its purpose?

      

    那么这对我们有什么影响?那么,内部类实例有访问权限   到包含类实例的实例成员。这些   封闭的实例成员通过内部类引用   只是他们简单的名字,而不是通过 this (这在内部类中   指的是内部类实例,而不是相关的包含   类实例)

    另见What are the uses of inner classes in Java? Are nested classes and inner classes the same?

答案 3 :(得分:1)

内心类的目的

内部类表示一种特殊类型的关系,它可以访问外部类的所有成员(数据成员和方法),包括private。 嵌套类可以使代码更具可读性和可维护性,因为它只在一个地方对类进行逻辑分组。

答案 4 :(得分:0)

需要内部类的一个例子

假设您有一个Java GUI(图形用户界面)类,它充当聊天客户端,如Gchat或Facebook Chat。想想在类似于代表聊天客户端的类中需要存在哪些方法 - 您将需要一种方法来读取聊天框中的用户输入,实际将用户输入发送到服务器的方法以及用户的任何方式正在聊天,即使是一种检测到你正在打字的方法,以便Gchat可以向你的朋友显示“XZY正在输入”文字等。

我们的示例中需要两种类型的方法

因此,应该清楚的是,需要两种不同类型的方法来驱动您的聊天客户端应用程序:1。聊天客户端特定的方法,如那些将从聊天框中读取用户输入并将用户输入发送到服务器。 2.事件处理方法,它将响应聊天客户端窗口中发生的实际事件 - 比如点击“返回”键,检测一致的输入等等。

因为很明显需要两种不同类型的方法,然后从面向对象设计的角度看,我们应该有两个不同的类:一个用于聊天客户端特定方法的类和一个用于事件的类处理方法。这确实遵循了通常的面向对象设计实践 - 因为我们正在创建专门从事他们所做工作的类。

有两个单独的课程的问题

但是,在这个特定的例子中,有两个单独的类存在问题。而且问题在于事件处理代码与属于聊天客户端的代码非常相关/相关。这是有道理的,正如我们之前在GChat示例中所讨论的那样;一旦GChat中的用户点击应该触发事件的键盘上的“RETURN”或“ENTER”,该事件就应该从聊天客户端窗口中获​​取文本。并且,聊天客户端窗口将是聊天客户端类的特定实例(基本上是对象)。例如,如果您在GChat中与您的朋友Bob谈话,他将在Gmail中有一个窗口,您将在Gmail中打开一个窗口,每个窗口都是聊天客户端类的对象。因此,聊天客户端类将有两个独立的对象 - 一个用于您,另一个用于Bob。

现在,如果Bob键入内容并点击RETURN键,响应RETURN键的事件处理程序代码将需要能够与Bob的聊天客户端类对象进行通信,以便它可以从Bob的聊天中获取文本客户端类窗口,或实际存储该文本的文本字段。这里的关键是根据对象进行思考 - 使用GChat为每个人创建聊天客户端类的对象,因此您将拥有自己的对象,Bob将拥有自己的对象。这意味着事件处理代码将需要访问聊天客户端对象的文本字段 - 它是类的成员,以及实例变量。因此,应该清楚的是,事件处理代码需要访问聊天客户端类对象的成员才能有效地帮助。

为什么我们不将事件处理代码与聊天客户端代码结合起来?

将事件处理方法与一个大类中的聊天客户端特定方法相结合首先听起来是个好主意,但是存在一个大问题:如果事件处理代码和聊天客户端代码都需要从中继承一些代码不同的类,那么你就麻烦了,因为Java不支持多重继承 - 这意味着我们的一个“大类”不能从两个不同的类继承。

拯救的内部课程

现在,这就是创建内部类的原因 - 对于与我们上面描述的情况完全相同的情况。内部类的实例可以访问外部类的实例的成员,因为内部类只是外部类的另一个成员。而且,内部类甚至可以访问外部类的私有成员 - 是的,你确实正确读过它了!

阅读本文 - When should inner classes be used in Java?

答案 5 :(得分:0)

静态内部类到达外部类的私有静态字段。这意味着如果我在任何地方扩展Outer.Inner类,(因为Inner是静态的,我不必在扩展之前创建对象)我无法到达外类的私有字段。这对于上下文安全性非常有用。

答案 6 :(得分:0)

1)嵌套类表示一种特殊类型的关系,它可以访问外部类的所有成员(数据成员和方法),包括私有。

2)嵌套类用于开发更易读和可维护的代码,因为它只在一个地方对类和接口进行逻辑分组。

3)代码优化:需要更少的代码来编写。

答案 7 :(得分:0)

我将从不同的角度给出解释。请首先检查Java内部类的内存模型。然后,通过掌握一些编程方面的基本技能,您就会知道为什么要麻烦使用内部类。

请参见How inner class object resides in memory?

此外,通常您应该在外部类的构造函数中实例化内部类对象以使其“有意义”,有时,如果您确实想弄乱,可以提供一个getter方法来检索驻留在外部类实例中的内部类实例。该内部类实例。