实用程序类的常见做法是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()
之类的无用方法污染自动完成。还有哪些缺点?上升空间?
答案 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
方法在许多/某些情况下是解决此类冲突的错误。