【问题标题】:Java-Final class vs private constructor: Difference between java.util.Arrays and java.lang.MathJava-Final 类与私有构造函数:java.util.Arrays 和 java.lang.Math 之间的区别
【发布时间】:2023-11-18 10:02:01
【问题描述】:

我知道最终类(不能继承类)和私有构造函数(不能创建类的实例)之间的区别。但是为什么ArraysMath,Java 类都有私有构造函数,而Math 是最终类而Arrays 不是?

有什么区别?不是两个实用程序类吗?

谢谢

【问题讨论】:

  • 看起来Arrays 的作者只是忘记了finalize 类。它的构造函数仍然是private(并用抑制默认构造函数,确保不可实例化。)并且没有创建Arrays 的实例(当然没有反射),而public 的其余部分方法是static,因此它也是一个“实用程序”类。语义上MathArrays 都是“实用程序”。与 C# 相比,Java 缺少 static 类,如果 Java 一开始就有这样的类而不需要 finalize 一个类并放置一个 private 构造函数,那可能会很好。
  • 好问题。我唯一的猜测是他们忘记了。 (java.util.Objects 也标记为 final,构造函数为 private。私有构造函数抛出 AssertionError 并带有消息 "No java.util.Objects instances for you!": -))

标签: java constructor private final


【解决方案1】:

当类具有私有构造函数但不是最终类时,您可以在同一个类文件中定义具有公共构造函数并且可以实例化的内部类。但是您不能在该初始类文件之外定义任何子类。 例如,这将编译:

public class Animal {
  public void say() {
    System.out.printLn("Animal says:");
  }
  private Animal() {}

  public static class Cat extends Animal {
    public Cat() {super();}
    @Override public void say() {
      super.say();
      System.out.printLn("Meow");
    }
  }
}

但是,这(在另一个文件中定义)不会:

public class Dog extends Animal {
  public Dog() {super();} // compilation error here: The constructor Animal() is not visible
  @Override public void say() {
    super.say();
    System.out.printLn("Wuf");
  }
}

此技术允许您定义类层次结构,您可以完全控制哪些类型可以扩展您的类(因为所有这些子类型都必须在同一个类文件中枚举)。

也就是说,由于上述原因,java.util.Arrays 并未被定义为非最终版本 - 它可能只是实现者的疏忽,与所有匹配无关,因此迄今为止尚未修复。

【讨论】: