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

实用类的一个常见事情是给它们一个私有的构造函数 :

public final class UtilClass { private UtilClass() {} ... } 

但不幸的是,一些工具不喜欢那个私人的构造函数。 他们可能会警告说,它从来没有在课堂上被调用,它没有被testing覆盖,该块不包含评论,等等。

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

 public enum UtilClass {; ... } 

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

请注意,我并不是问一个Java枚举与一个具有公共静态final字段的类的优点是什么? 。 我不是决定一个事物列表应该是一堆常量还是一个枚举,我决定把一堆函数放在一个无构造函数的类或一个无价值的枚举中。

另外请注意,我其实不想这样做。 我只是想把这些权衡作为一般语言知识的一部分。

例如,使用枚举来污染自动完成,像UtilClass.values()这样的无用方法。 还有什么其他缺点? 上升空间?

一个好处是,你绝对保证,即使在课堂内部也不能创build任何实例。

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

Joshua Bloch关于这样的单例的“Effective Java”也适用于实用类:

…你会得到一个铁定的保证,除了声明的常量之外,不存在任何实例。 JVM做出这个保证,你可以依靠它。

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

使用enum实际上并不是一个枚举是丑陋和混乱。 我会说这是不够的。

“效用阶层”模式是完全合法的。 如果你的工具不喜欢它,这是工具的问题。

在实用类中的以下模式也提供了可以保证不存在实例的铁证:

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

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

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

 public final class UtilityClass { public static final UtilityClass Instance = new UtilityClass(); private UtilityClass () {} public static int Foo (int a, int b) { return a+b; } } 

但是既然你是这个类的devise者,那么破坏你自己的代码契约是没有任何意义的。

一般来说,我读过的大多数软件devise书都反对使用静态方法 。 除非它们是真正的效用方法:从某种意义上说,它们决不会要求任何状态。 即便如此,实现一个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);调用它UtilityClass.Instance.Foo(2,5); 。 稍后在编码过程中执行引入状态转换将会更困难。 因此静态方法很难维护。

实例有用的原因是,如果有一种情况下,它可以在很多模式中使用它们,例如,在某种情况下,它依赖于应该完成的任务,通过使用static方法,可以减lessdynamic方法,因为Java不会“ t支持方法指针(出于很好的理由)。 因此非静态方法更加dynamic和有用。

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

总而言之:Java是build立在面向对象编程的基础之上的。 这意味着编程人员使用“ c世界”,而解释器/运行时使用“实体世界”。 我同意这两个词之间有很多冲突。 但static方法在很多/某些情况下是解决这种冲突的错误。