37

对实用程序类的常见做法是给它们一个私有构造函数

public final class UtilClass {
    private UtilClass() {}

    ...
}

但不幸的是,有些工具不喜欢那个私有构造函数。他们可能会警告它永远不会在类中调用,它没有被测试覆盖,该块不包含注释等。

如果你这样做,很多警告就会消失:

public enum UtilClass {;
    ...
}

我的问题是:除了对未来开发人员的无休止的仇恨之外,在 Java 中没有值的枚举和具有私有构造函数的类之间有什么重要区别?

请注意,我不是在问Java 枚举与具有公共静态最终字段的类相比有什么优势?. 我不是在一个事物列表应该是一堆常量还是一个枚举之间做出决定,我是在将一堆函数放在一个无构造函数的类中还是一个无值的枚举中做出决定。

另请注意,我实际上并不想这样做。我只想知道作为一般语言知识的一部分的权衡。

例如,使用枚举会使用无用的方法(如UtilClass.values(). 还有哪些其他缺点?好处?

4

4 回答 4

35

enum用于实际上不是枚举的东西是丑陋和令人困惑的。我会说这是足够的理由不这样做。

“实用程序类”模式是完全合法的。如果您的工具不喜欢它,那是工具的问题。

于 2014-10-28T22:31:46.767 回答
31

一个好处是您绝对可以保证不能创建任何实例,即使是在类内部也是如此。

一个缺点是这超出了枚举的通常意图。但是,我们已经对使用枚举实现的单例进行了此操作。

Joshua Bloch 的“Effective Java”中关于此类单例的这一点也适用于实用程序类:

...你得到一个铁定的保证,除了声明的常量之外,不能有任何实例。JVM 做出了这个保证,你可以依赖它。

免责声明:我没有使用过这种模式,也不推荐或反对它。

于 2014-10-28T22:07:18.997 回答
9

实用程序类中的以下模式还提供了不存在实例的铁定保证:

public abstract class Util {
    private Util() { throw new Error(); }
    ... // static methods
}

此外,您没有额外的不相关的静态方法,由枚举提供。

于 2014-10-28T22:15:53.577 回答
6

唯一的区别是你仍然可以在你的类中调用构造函数:

public final class UtilityClass {

    public static final UtilityClass Instance = new UtilityClass();

    private UtilityClass () {}

    public static int Foo (int a, int b) {
         return a+b;
    }

}

但是由于您是该类的设计者,因此破坏您自己的代码合同没有任何意义。

一般来说,我读过的大多数软件设计书籍都反对使用静态方法。除非它们真的是实用方法:从某种意义上说,它们永远不需要任何状态。即便如此,实现单例模式也只是很小的努力,这样,当时机成熟时,您可以为它分配状态:

public final class UtilityClass {

    public static final UtilityClass Instance = new UtilityClass();

    private UtilityClass () {}

    public int Foo (int a, int b) {
         return a+b;
    }

}

并用UtilityClass.Instance.Foo(2,5);. 稍后在编码过程中执行引入状态转换将更加困难。因此静态方法更难维护。

实例有用的原因是您可以在很多模式中使用它们,例如策略,如果在某个情况下它取决于应该做什么,......通过使用static方法,可以降低方法的动态性,因为 Java 没有支持方法指针(有充分的理由)。因此,非静态方法更加动态和有用。

此外,一些安全研究人员认为,使用static修饰符分析代码更加困难,因为它们可以从任何地方访问,并且副作用难以预测(例如在自动安全分析工具中):假设您有一个未完全实现的类,那么您仍然可以分析字段以了解它可以访问哪些方法,从而分析可能的副作用(网络使用情况、文件 IO ......)。这可以生成应验证的每个类别的可能危害列表。至少如果我理解我的一位研究人员的博士论文是正确的。因此,非静态方法允许更多的修饰符分析。

总结:Java 是建立在面向对象编程的原则之上的。这意味着编译器使用“世界”,解释器/运行时使用“实例世界”。我同意这两个词之间有很多冲突。但是在许多/某些情况下,解决此类冲突的方法是错误的。static

于 2014-10-28T22:11:49.633 回答