为什么在类中有一个公共静态类

16

我在查看一些代码时看到了这个:

public class A {
    public A(SomeObject obj) {
      //Do something
    }
    //Some stuff
  public static class B {
    //Some other stuff
  }
}

我想知道既然内部类是public为什么要将其嵌套而不是作为一个单独的类?此外,我能在这里这样做吗:new A.B(SomeObject)?我觉得这违背了静态类的目的,但我也看到过这种实现方式,所以想知道。

6个回答

18

我想知道既然内部类是public的,为什么要将其作为嵌套类而不是单独的类?

这真的是需要问编写该类的人的问题。不过它可以让外部类充当“小命名空间”——如果嵌套类在外部类的上下文中有用,那么这似乎是合理的。它表明了两个类之间的紧密耦合关系。我经常在构建器模式的上下文中看到这种情况:

Foo foo = new Foo.Builder().setBar(10).build();

在这里,我认为将Foo.Builder嵌套到Foo中比作为同等级类的FooBuilder更合理。

请注意,与仅无关联类相比,它也具有一些可见性差异。

在这里,我可以这样做吗:new A.B(SomeObject)

不行,因为B没有带有SomeObject参数的构造函数 - 只有A有(在您提供的示例中)。

我觉得这违背了静态类的目的

您应该尝试确切地确定您认为静态类的目的是什么,以及这种方式如何违反它。当前这个陈述太模糊了,无法进行实际讨论。


5
您需要一个类似于这样的内部类,以便:
  • 您可以将仅存在于支持外部类的类封装起来。
  • 您希望能够访问外部类或其他嵌套类的私有成员。
  • 您需要一个具有静态字段的嵌套类(我知道这是一个较弱的理由)
  • 您拥有一个非常通用的名称,如LockSync,您不希望与同一包中的其他类混淆使用相同名称的类。

我可以在这里这样做:new A.B(SomeObject) 吗?

可以。

我觉得这违背了静态类的目的

习惯了就好了,一旦开始你可能会难以保持你的整个程序不变成一个file.java文件;)


2

1. 静态内部类被称为顶层类。

2. 这个静态类可以直接访问其外部类的静态方法和变量。

3. 你需要从外部这样初始化静态内部类...

    A a = new A();
    A.B b = new A.B();

4. new A.B(SomeObject) 无法工作,因为你 没有一个构造函数 接受 SomeObject 作为参数...

5. 但当内部类是非静态的时候,它会有一个隐含的对外部类的引用。

6. 外部和内部类可以 继承不同的类

7. 使用内部类,接口方法 可以以不同或相同的方式被实现 多次


2

这个模式在构建器模式中经常被使用。它不仅清晰地表明了类和其构建器之间的关系,还隐藏了丑陋的构建器构造函数/工厂,并使构建器更易读。例如,在您需要构建的对象具有可选和非可选属性的情况下。

public class AnObject {
   public static class AnObjectBuilder {

       private AnObject anObject;

       private AnObjectBuilder() {
       }

       private void newAnObjectWithMandatory(String someMandatoryField, ...) {
           anObject = new AnObject(someMandatoryField,...)
       }

       public AnObjectBuilder withSomeOptionalField(String opt) {
           ...
       }
   }

   public static AnObjectBuilder fooObject() {
        return (new AnObjectBuilder()).newAnObjectWithMandatory("foo")
   }

   public static AnObjectBuilder barObject() {
        return (new AnObjectBuilder()).newAnObjectWithMandatory("bar")
   }
}

客户端代码需要先调用 AnObjectBuilder 类的静态方法,然后使用可选的构建器方法:

AnObject.fooObject("foo").withSomeOptionalField("xxx").build(); 而无需创建构建器对象。

非常易读 :)


2

你的链接当前指向了最后一个答案。我建议使用这个链接代替:https://dev59.com/j2gt5IYBdhLWcg3wywdJ - Rajesh J Advani
根据下面给出的其他答案,我认为你对于 new A.B(SomeObject) 的回答是错误的,这其实很有道理,因为静态类没有构造函数。 - noMAD

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接