理解内部类(为什么存在内部类)

时间:2016-02-29 11:58:18

标签: java oop inner-classes

我正在阅读 Thinking in Java ,关于内部类存在的原因以及它们帮助解决的问题。

本书试图给出的最令人信服的理由是:

  

每个内部类都可以独立地从实现继承。   因此,内部类不受外部类的限制   已经从实现继承。

请帮助我复习一下:

由于Java不支持多重继承,因此存在内部类。这个(多重继承)可以在Inner类中完成,Outer class可以有多个内部类,并且每个类都可以从不同的类继承。因此,通过这种方式,可以实现多重继承。我能想到的另一个原因是Inner classes解决了OOP设计原则composition better than inheritance

更新

我发现的大多数解释就像下面的答案一样。例如,GUI框架中用于处理事件处理程序的Inner类。没有提到书中引用的原因。我不是说下面的答案不是好的。其实。我真的很感激他们(+1)。我只是想知道这本书有什么问题吗?

3 个答案:

答案 0 :(得分:2)

  

为什么要使用嵌套类?

     

使用嵌套类的令人信服的理由包括:

     
  • 这是一种逻辑分组仅在一个中使用的类的方法   place:如果一个类只对另一个类有用,那么它就是   合乎逻辑地将它嵌入该类中并将两者保持在一起。嵌套   这样的"助手班"使他们的包更加简化。
  •      
  • 它增加了封装:考虑两个顶级类A和B,   其中B需要访问否则将被声明的A成员   私人的。通过将B类隐藏在A类中,可以声明A&#39的成员   私人和B可以访问它们。另外,B本身可以隐藏   来自外部世界。
  •      
  • 它可以带来更易读和可维护的代码:嵌套小   顶级类中的类使代码更接近它所在的位置   使用。

Oracle文档:Understanding inner classes

以下问题可能会让您感兴趣 -

What is the reason for making a nested class static in HashMap or LinkedList?

<强>更新

  

未提及书中引用的原因。 ... 我只是想知道   这本书有什么问题吗?

我不认为您突出显示的陈述有任何问题。

Each inner class can independently inherit from an implementation:这是对的。就像外部类一样,它可以独立地从实现继承。只要将它们都视为单独的类。

Thus, the inner class is not limited by whether the outer class is already inheriting from an implementation:由于两者都是独立的类,外部类是否已经从实现继承并不重要。内部类也可以从实现继承。毕竟它也是一堂课。

答案 1 :(得分:2)

在阅读了本书中引用的最令人信服的理由后,您想到多重继承的想法有点令人费解。当一个类(内部或非内部)想要从多个具体实现继承行为时,多重继承会受到质疑。因此,与Java中的其他语言不同,您不能定义类:

class Child extends Father, Mother {
   // Child wants to inherit some behavior from Father and some from Mother
}

正如您所看到的,内部类所做的任何事情都无法以直接的方式纠正或解决此Java决策(不支持多重继承)。

那么为什么它们存在,你可能想知道!好吧,在Java中,每个类都是顶级或内部(也称为嵌套)。在另一个类中定义的任何类都是内部类,任何不是这样的类都是顶级类。

当然,人们可能想知道为什么要在其他类中定义类(即行为)。 Aren的顶级课程足够吗?

答案是肯定的。 Java总是可以只有 顶级类。但是(也许)这个想法是没有充分理由限制类成为其他类的成员!就像任何预定义类型(例如IntegerString等)都可以成为类的成员:

class Person {
  private String name; // a field the models a Person's name
}

程序员应该能够在课堂上定义一个人的兴趣行为

class Person {
  private String name; // a field the models a Person's name
  private Address address; // address is a type defined here
  static class Address {
    String street; 
    String city;
  }
}

这里有很多内容,尤其是privatestatic等内容,它们被称为修饰符。有很多关于它们的技术细节,但让我们稍后再回过头来看看它们。基本思想是能够将行为定义为另一个类的一部分。 Address类可以在 Person类之外定义作为顶级类吗?当然。但是拥有这个设施会派上用场。

现在,由于引入了这个工具,它开始服务于另一个目的,这个目的被称为提供代码作为数据。这就是设计模式的出现,直到大约10年前才开始考虑内部类可以用来以代码的形式提供数据。也许这对你来说有点令人费解。请考虑以下代码,我几乎逐字地从JDK类中获取:java.lang.String.java

public static final Comparator<String> CASE_INSENSITIVE_ORDER
                                     = new CaseInsensitiveComparator();
private static class CaseInsensitiveComparator
        implements Comparator<String> {

    public int compare(String s1, String s2) {
        int n1 = s1.length();
        int n2 = s2.length();
        // details excluded for brevity
        // return -1, 0, 1 appropriately
    }
}

这里发生了什么?

我们需要一种方法来将String与另一个String进行比较,我们需要能够进行不区分大小写的比较。因此,我们在外部类中创建了Comparator接口的实现String!这不方便吗?如果内部阶级不在那里,那就必须是:

public class String {
  // ... the whole String class implementation

}
class CaseInsensitiveComparator
            implements Comparator<String> {
   // implements the comparator method
}

并且那不是“不好的”&#39;本身,但它意味着许多类污染名称空间。内部类将行为的范围限制为外部类。这很方便,正如你可能会看到的那样。这种情况下的数据是Comparator接口的实现,代码也是如此,因为我们正在_new_ing我们定义的内部类。

使用匿名内部类(特别是在您希望代码充当数据的情况下)进一步利用此功能,直到Java 7,它们被Java 8中的Lambda Expressions有效替换。现在,您可能看不到任何使用匿名内部类的新代码(换句话说,语言都在演变)。

答案 2 :(得分:1)

如果您正在寻找用例,我只能告诉您我经常使用它们的情况,基本上是这两件事:

  1. 我用来帮助实现一些内部逻辑的静态内部类。这些通常是某种形式的元组或一些简单的容器。例如:地图中包含“条目”,基本上只是对。

  2. 表示运行时父子关系。这些是非静态内部类。例如:我有一个Job类,它可以实例化多个Task内部类,这些内部类需要查看作业中的数据以进行处理。

  3. 当然可能有更多的用例......