没有值的java枚举与私有构造函数的实用程序类之间的区别

时间:2014-10-28 21:33:53

标签: java enums private-constructor

实用程序类的常见做法是give them a private constructor

public final class UtilClass {
    private UtilClass() {}

    ...
}

但遗憾的是,有些工具不喜欢私有构造函数。他们可能会警告它从未被调用过类,它没有被测试覆盖,块不包含注释等。

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

public enum UtilClass {;
    ...
}

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

请注意,我询问What's the advantage of a Java enum versus a class with public static final fields?。我不是在决定一系列事物应该是一堆常量还是一个枚举,我决定将一堆函数放在无构造函数的类或无值的枚举中。

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

例如,使用枚举会使用诸如UtilClass.values()之类的无用方法污染自动完成。还有哪些缺点?上升空间?

4 个答案:

答案 0 :(得分:33)

enum用于实际上不是枚举的内容是丑陋和令人困惑的。我说有足够的理由不去做。

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

答案 1 :(得分:26)

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

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

来自" Effective Java"约书亚布洛赫关于这些单身人士也适用于公用事业班:

  

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

免责声明:我没有使用过这种模式,我不建议支持或反对它。

答案 2 :(得分:8)

实用程序类中的以下模式还提供了可以没有实例的铁定保证:

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

此外,您没有其他无关的静态方法,由枚举提供。

答案 3 :(得分: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;
    }

}

但是既然你是那个班级的设计师,打破自己的代码合同就没有任何意义。

一般来说,我读过的大多数软件设计书都反对使用静态方法。除非它们真的是实用方法:从某种意义上说,它们永远不会需要任何状态。即便如此,实现 Singleton 模式只需要很少的努力,以便在时间到来时,您可以为其分配状态:

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);调用它。稍后在编码过程中执行引入状态转换会更加困难。 因此,静态方法难以维护。

实例之所以有用,是因为你可以在很多模式中使用它们,比如策略,如果有一次它取决于应该做什么,......使用{{1方法,一个使方法不那么动态,因为Java不支持方法指针(出于好的理由)。 因此,非静态方法更具动态性和实用性。

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

总结:Java是基于面向对象编程的原则构建的。这意味着" c lass world"由 c ompiler和" i nstance world"通过 i nterpreter / runtime。我同意这两个词之间存在很多冲突。但static方法在许多/某些情况下是解决此类冲突的错误。