Java中的静态嵌套类,为什么?

我正在查看LinkedList的Java代码,并注意到它使用了静态嵌套类Entry

 public class LinkedList<E> ... { ... private static class Entry<E> { ... } } 

什么是使用静态嵌套类,而不是一个正常的内部类的原因是什么?

我能想到的唯一原因是Entry不能访问实例variables,所以从OOP的angular度来看,它具有更好的封装性。

但我想可能还有其他的原因,也许是performance。 它可能是什么?

注意。 我希望我已经得到了我的条款正确的,我会把它称为一个静态的内部类,但我认为这是错误的: http : //java.sun.com/docs/books/tutorial/java/javaOO/nested.html

你链接到的Sun页面在两者之间有一些关键的区别:

嵌套类是其封闭类的成员。 非静态嵌套类(内部类)可以访问封闭类的其他成员,即使它们被声明为私有。 静态嵌套类不能访问封闭类的其他成员。

注意:静态嵌套类与其外部类(和其他类)的实例成员交互,就像任何其他顶级类一样。 实际上,静态嵌套类在行为上是嵌套在另一个顶级类中的顶级类,以便于打包。

LinkedList.Entry不需要LinkedList.Entry ,因为它只被LinkedList (还有一些其他接口也有静态嵌套类Entry ,比如Map.Entry – 同一个概念)。 而且由于它不需要访问LinkedList的成员,所以它是静态的 – 这是一个更清洁的方法。

正如Jon Skeet所指出的那样 ,我认为如果你使用的是一个嵌套类是一个更好的主意,那么从静态开始,然后根据你的使用情况决定它是否真的需要是非静态的。

在我看来,当你看到一个内部类的时候,这个问题应该是相反的 – 它是否真的需要成为一个内部类,带有额外的复杂性和隐含的(而不是明确的,更清晰的IMO)引用的实例包含类的?

请注意,我偏爱C#风扇 – C#没有内部类的等价物,虽然它有嵌套types。 我不能说我已经错过了内部课程:)

这里没有明显的内存保留问题需要考虑。 由于非静态内部类保持对其“外部”类的隐式引用,因此如果内部类的实例被强引用,则外部实例也被强引用。 当外部类不是垃圾收集时,这可能会导致一些头部划伤,即使看起来没有任何引用它。

那么,一方面,非静态的内部类有一个额外的,隐藏的领域,指向外部类的实例。 所以如果Entry类不是静态的,那么除了不需要的访问之外,它将包含四个指针而不是三个。

通常我会说,如果你定义了一个基本上可以充当数据成员集合的类,就像C中的“struct”一样,可以考虑使它成为静态的。

静态嵌套类就像任何其他的外部类,因为它没有外部类成员的访问。

为了便于打包,我们可以将静态嵌套类放到一个外部类中,以实现可读性。 除此之外,没有其他静态嵌套类的用例。

这种用法的例子,你可以在Android R.java(资源)文件中find。 Android的Res文件夹包含布局(包含屏幕devise),可绘制文件夹(包含用于项目的图像),值文件夹(其中包含string常量)等。

正弦所有的文件夹都是Res文件夹的一部分,android工具生成一个R.java(资源)文件,内部包含大量的静态嵌套的类为他们的每个内部文件夹。

下面是在android中生成的R.java文件的外观和感觉:这里只是为了方便打包。

 /* AUTO-GENERATED FILE. DO NOT MODIFY. * * This class was automatically generated by the * aapt tool from the resource data it found. It * should not be modified by hand. */ package com.techpalle.b17_testthird; public final class R { public static final class drawable { public static final int ic_launcher=0x7f020000; } public static final class layout { public static final int activity_main=0x7f030000; } public static final class menu { public static final int main=0x7f070000; } public static final class string { public static final int action_settings=0x7f050001; public static final int app_name=0x7f050000; public static final int hello_world=0x7f050002; } } 

在构build器模式中使用静态内部类。 静态内部类可以实例化它的只有私有构造函数的外部类。 所以你可以使用静态内部类来实例化只有私有构造函数的外部类。 你不能对内部类做同样的事情,因为你需要在访问内部类之前创build外部类的对象。

 class OuterClass { private OuterClass(int x) { System.out.println("x: " + x); } static class InnerClass { public static void test() { OuterClass outer = new OuterClass(1); } } } public class Test { public static void main(String[] args) { OuterClass.InnerClass.test(); // OuterClass outer = new OuterClass(1); // It is not possible to create outer instance from outside. } } 

这将输出x:1

简单的例子:

 package test; public class UpperClass { public static class StaticInnerClass {} public class InnerClass {} public static void main(String[] args) { // works StaticInnerClass stat = new StaticInnerClass(); // doesn't compile InnerClass inner = new InnerClass(); } } 

如果非静态类不能在上层类的实例中实例化(所以在main是静态函数的例子中不这样做)

静态与正常的原因之一是与类加载有关。 你不能在它的父类的构造函数中实例化一个内部类。

PS:我一直都明白“嵌套”和“内在”是可以互换的。 在术语中可能存在微妙的细微差别,但大多数Java开发人员也会理解。

http://docs.oracle.com/javase/tutorial/java/javaOO/whentouse.html

如果您需要访问封闭实例的非公共字段和方法,请使用非静态嵌套类(或内部类)。 如果您不需要此访问权限,请使用静态嵌套类。

非静态内部类可能会导致内存泄漏,而静态内部类将防止它们。 如果外部类拥有相当多的数据,可能会降低应用程序的性能。

根据下面的Oracle站点是使用嵌套类(静态或非静态)的关键好处: http : //docs.oracle.com/javase/tutorial/java/javaOO/nested.html

为什么使用嵌套类?

使用嵌套类的强有力的理由包括:

这是一种逻辑分组的方法,只在一个地方使用:如果一个类只对另一个类有用,那么它是
合乎逻辑地把它embedded到这个类中,并把它们放在一起。 嵌套这样的“帮助类”使得它们的包更加简化。

它增加封装:考虑两个顶级类,A和B,
B需要访问A的成员,否则将被宣布为私有。 通过在类A中隐藏类B,可以将A的成员声明为私有,并且B可以访问它们。 另外,B本身可以被外界隐藏起来。

它可以导致更易于读取和维护的代码:在顶层类中嵌套小类可以使代码更接近它的使用位置

在某些情况下,使用静态嵌套类而不是非静态嵌套类可能会节省空间。 例如:在一个类中实现一个Comparator ,例如Student。

 public class Student { public static final Comparator<Student> BY_NAME = new ByName(); private final String name; ... private static class ByName implements Comparator<Student> { public int compare() {...} } } 

然后static确保Student类只有一个Comparator,而不是在每次创build一个新的学生实例时都实例化一个新的Comparator。

我不知道性能差异,但正如你所说,静态嵌套类不是封闭类的一个实例的一部分。 似乎更简单的创build一个静态嵌套类,除非你真的需要它是一个内部类。

这有点像为什么我总是把我的variables做成Java的最终版 – 如果它们不是最终的,我知道有一些有趣的事情发生在他们身上。 如果您使用内部类而不是静态嵌套类,应该有一个很好的理由。

内部阶层的优势 –

  1. 一次性使用
  2. 支持和改进封装
  3. 可读性
  4. 私人字段访问

不存在外部阶级的内部阶层是不存在的。

 class car{ class wheel{ } } 

内部有四种types。

  1. 正常的class级
  2. 方法本地内部类
  3. 匿名的内部类
  4. 静态的内部类

点—

  1. 从静态的内部类,我们只能访问外部类的静态成员。
  2. 在内部类中,我们可以声明静态成员。
  3. 以便在外部类的静态区域中调用正常的内部类。

    Outer 0=new Outer(); Outer.Inner i= O.new Inner();

  4. 以便在外部类的实例区域中调用正常的内部类。

    Inner i=new Inner();

  5. 以便在外部类的外部调用正常的内部类。

    Outer 0=new Outer(); Outer.Inner i= O.new Inner();

  6. inside Inner class这个指向内部类的指针。

    this.member-current inner class outerclassname.this--outer class

  7. 对于内部类适用修饰符是 – public,default,

    final,abstract,strictfp,+private,protected,static

  8. outer $ inner是内部类名称的名称。

  9. 内部类的实例方法,那么我们可以访问外部类的静态和实例字段。

10.inner类里面的静态方法然后我们只能访问静态字段

外部类。

 class outer{ int x=10; static int y-20; public void m1() { int i=30; final j=40; class inner{ public void m2() { // have accees x,y and j } } } }