【问题标题】:Avoid instantiating a class in java避免在java中实例化一个类
【发布时间】:2009-08-25 05:31:56
【问题描述】:
最近遇到一个问题:如何避免实例化 Java 类?
但是,我的回答是:
如果您不想实例化一个类,请使用“抽象”修饰符。例如:javax.servlet.HttpServlet,被声明为抽象的(尽管它的方法都不是抽象的)以避免实例化。
声明一个无参数私有构造函数。
现在我的问题是
a) 还有其他方法吗?
b) 为什么有人不想实例化一个类? - 在 SO 中搜索后,我从this 了解到,可以使 Util 类不实例化。还有其他我们不想在 OOP 中实例化类的地方吗?
【问题讨论】:
标签:
java
class
instantiation
【解决方案1】:
想到四个原因:
- 允许实例化子类但不允许实例化父类;
- 禁止直接实例化,而是提供工厂方法返回并在必要时创建实例;
- 因为所有实例都是预定义的(例如一副纸牌中的花色),尽管从 Java 5 开始,推荐使用类型安全枚举;和
- 课程真的不是课程。它只是静态常量和/或方法的持有者。
作为 (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
}
}
注意:不需要无参数构造函数,因为显式定义了另一个构造函数。
【解决方案2】:
不是你的问题的真正答案,只是一个注释:
当你创建一个私有的无参数构造函数来防止你的实用程序类的实例化时,你应该让构造函数抛出一个异常(例如 UnsupportedOperationException)。这是因为您实际上可以通过反射访问私有成员(包括构造函数)。请注意,如果您这样做,则应附上注释,因为定义构造函数来防止实例化类有点违反直觉。
使实用程序类抽象不是一个好主意,因为它使类看起来像是要扩展的,而且您可以扩展该类并实例化它。
【解决方案4】:
我认为不想实例化一个类的最常见原因是当您处理一个静态类时,因此是它的静态方法。您不希望有人尝试实例化该类。同样,当您处理工厂类时,或者在某些情况下,许多单例类将隐藏它们的构造函数,以免以正常方式实例化。
【解决方案5】:
另一种使类不可实例化的方法是将其声明为私有内部类,然后不提供任何方法在周围的类中实例化它。但这(IMO)毫无意义。
如果实例化一个类没有意义,你希望它是不可实例化的。如果该类实际上只是(静态)辅助方法的集合,或者如果该类“不完整”,您通常会这样做。不完整可能在语法上很明显(即抽象方法),但还有其他类型的不完整。例如,您可以为所有方法提供默认的默认实现,并要求其中一个或多个被覆盖,以便类做一些有用的事情。
使类不可实例化(或至少不可直接实例化)的另一个原因是您的应用程序是否需要控制实例化。例如,java.util.regex.Pattern 类不能直接实例化,因此 JRE 可以(可以)维护预编译正则表达式的缓存。