我正在阅读 Thinking in Java ,关于内部类存在的原因以及它们帮助解决的问题。
本书试图给出的最令人信服的理由是:
每个内部类都可以独立地从实现继承。 因此,内部类不受外部类的限制 已经从实现继承。
请帮助我复习一下:
由于Java不支持多重继承,因此存在内部类。这个(多重继承)可以在Inner类中完成,Outer class
可以有多个内部类,并且每个类都可以从不同的类继承。因此,通过这种方式,可以实现多重继承。我能想到的另一个原因是Inner classes解决了OOP设计原则composition better than inheritance。
更新
我发现的大多数解释就像下面的答案一样。例如,GUI框架中用于处理事件处理程序的Inner类。没有提到书中引用的原因。我不是说下面的答案不是好的。其实。我真的很感激他们(+1)。我只是想知道这本书有什么问题吗?
答案 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总是可以只有 顶级类。但是(也许)这个想法是没有充分理由限制类成为其他类的成员!就像任何预定义类型(例如Integer
,String
等)都可以成为类的成员:
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;
}
}
这里有很多内容,尤其是private
,static
等内容,它们被称为修饰符。有很多关于它们的技术细节,但让我们稍后再回过头来看看它们。基本思想是能够将行为定义为另一个类的一部分。 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)
如果您正在寻找用例,我只能告诉您我经常使用它们的情况,基本上是这两件事:
我用来帮助实现一些内部逻辑的静态内部类。这些通常是某种形式的元组或一些简单的容器。例如:地图中包含“条目”,基本上只是对。
表示运行时父子关系。这些是非静态内部类。例如:我有一个Job
类,它可以实例化多个Task
内部类,这些内部类需要查看作业中的数据以进行处理。
当然可能有更多的用例......