21

最近我遇到了一个问题:如何避免实例化 Java 类?

但是,我回答说:

  1. 如果您不想实例化一个类,请使用“抽象”修饰符。例如:javax.servlet.HttpServlet,被声明为抽象的(尽管它的方法都不是抽象的)以避免实例化。

  2. 声明一个无参数私有构造函数。

现在我的问题是a)还有其他方法吗?b) 为什么有人不想实例化一个类?- 在 SO 中搜索后,我从中了解到Util 类可以不实例化我们不想在 OOP 中实例化一个类的任何其他地方?

4

5 回答 5

29

四个原因浮现在脑海:

  1. 允许实例化子类但不允许实例化父类;
  2. 不允许直接实例化,而是提供工厂方法来返回并在必要时创建实例;
  3. 因为所有实例都是预定义的(例如一副纸牌中的花色),尽管从 Java 5 开始,推荐使用类型安全枚举;和
  4. 课堂真的不是课堂。它只是静态常量和/或方法的持有者。

作为 (2) 的示例,您可能想要创建规范对象。例如,RGB 颜色组合。您不想创建任何 RGB 组合的多个实例,因此您可以这样做:

public class MyColor {
  private final int red, green, blue;

  private MyColor(int red, int green, int blue) {
    this.red = red;
    this.green = green;
    this.blue = blue;
  }

  public static MyColor getInstance(int red, int green, int blue) {
    // if combo already exists, return it, otherwise create new instance
  }
}

注意:不需要无参数构造函数,因为显式定义了另一个构造函数。

于 2009-08-25T05:34:39.447 回答
14

不是您问题的真正答案,而只是一个注释:

当你创建一个私有的无参数构造函数来防止你的实用程序类的实例化时,你应该让构造函数抛出一个异常(例如 UnsupportedOperationException)。这是因为您实际上可以通过反射访问私有成员(包括构造函数)。请注意,如果您这样做,则应附上注释,因为定义构造函数以防止实例化类有点违反直觉。

使实用程序类抽象不是一个好主意,因为它使类看起来像是要扩展的,而且您可以扩展该类并实例化它。

于 2009-08-25T14:04:16.953 回答
3

有时您只想避免其他人实例化您的对象,以便完全控制所有现有实例。一个例子是单例模式

于 2009-08-25T05:35:14.983 回答
2

我认为不想实例化一个类的最常见原因是当你处理一个静态类时,因此是它的静态方法。您不希望有人尝试实例化该类。同样,当您处理工厂类时,或者在某些情况下,许多单例类将隐藏它们的构造函数,以免以正常方式实例化。

于 2009-08-25T05:34:25.750 回答
1

使类不可实例化的另一种方法是将其声明为私有内部类,然后不提供任何方法在周围类中实例化它。但这(IMO)毫无意义。

如果实例化一个类没有意义,你希望它是不可实例化的。如果该类实际上只是(静态)辅助方法的集合,或者如果该类“不完整”,您通常会这样做。不完整性可能在语法上很明显(即抽象方法),但还有其他类型的不完整性。例如,您可以为所有方法提供默认的默认实现,并要求其中一个或多个被覆盖,以便类做一些有用的事情。

使类不可实例化(或至少不能直接实例化)的另一个原因是您的应用程序是否需要控制实例化。例如,java.util.regex.Pattern 类不能直接实例化,因此 JRE 可以(可以)维护预编译正则表达式的缓存。

于 2009-08-25T05:43:45.233 回答