我有一个应用程序,我有一个名为PlausibilityChecker
的类。此类只有静态方法,如checkZipcodeFormat
或checkMailFormat
。我在GUI类中使用它们来检查输入,然后再将它发送到较低层。
这是好习惯吗?我以为我只使用静态方法,因此我不必关心将实例传递给GUI类,或者在每个没有引用gui对象的gui类中都有一个实例字段
我注意到Files
Java NIO
类var chartHelp = angular.element(document.getElementById('chart-help'));
$document.scrollToElement(chartHelp, 30, 500).then(function() {
console && console.log('You just scrolled to chart-help!');
});
只有静态方法,所以我认为这可能是错误的。
答案 0 :(得分:35)
我会说你做得对。除此之外,还有一些针对实用程序类的建议:
static final
,否则类中没有字段。另外,请确保此字段也是不可变的,例如String
秒。final
,以便其他程序员无法扩展它。private
,所以没有其他类可以创建你的实用程序类的实例(使用反射或类似的东西会做,但没有必要去与班级保护)。你为什么不这样做?嗯,这是一个奇怪的情况,你需要/需要注入实用程序类的实例,例如通过界面,而不是直接在你的班级使用它。 Here's an example of this。这种设计很奇怪但可能会发生(如上面的链接所示),但如果你不能在这种情况下运行,最好的建议是保持构造函数private
。有很多库提供实用程序类,以帮助程序员完成我们的工作。其中最着名的是Apache Common个库集。它是开源的,您可以检查代码,看看他们如何设计这些实用程序类以创建您的。 (免责声明:我不工作或支持这些库,我很乐意使用它们)
答案 1 :(得分:11)
在Java 8中,您现在可以将静态实用程序类更改为具有静态实现的接口。这消除了使类最终并且必须提供私有构造函数的需要。它就像将'class'更改为'interface'并删除最后一个单词(如果你拥有它)一样简单(所有接口都是抽象的,所以它们不能是最终的)。由于接口方法始终是公共的,因此您可以从中删除任何公共范围。如果您有一个私有构造函数,那么也删除它(您无法使用构造函数编译接口,因为它们无法实例化)。它的代码更少,看起来更干净。您不必重构任何已经使用它的类。
答案 2 :(得分:4)
不要担心子类化或实例化。 JDK中的以下实用程序类可以进行子类化或实例化,但是在这些年中没有人滥用它们。人们 愚蠢。
java.beans.Beans
java.beans.PropertyEditorManager
java.lang.invoke.LambdaMetafactory
java.lang.reflect.Modifier
java.net.URLDecoder ...but not URLEncoder:)
javax.management.DefaultLoaderRepository
javax.management.Query
javax.management.loading.DefaultLoaderRepository
javax.management.relation.RoleStatus
javax.print.ServiceUI
javax.swing.UIManager
javax.swing.plaf.basic.BasicBorders
javax.swing.plaf.basic.BasicGraphicsUtils
javax.swing.plaf.basic.BasicHTML
javax.swing.plaf.basic.BasicIconFactory
javax.swing.plaf.metal.MetalBorders
javax.swing.plaf.metal.MetalIconFactory
javax.swing.text.Utilities
javax.swing.text.html.HTML
但是,作为公共API,您确实要禁止默认构造函数,否则javadoc页面上有一个未记录的构造函数,这是一个笨拙和令人困惑的问题。对于您自己的内部API,没关系,无人问津。
没有理由压制子类化。如果有人想要将实用程序类子类化,无论出于何种原因,请让他。当然,私有构造函数会将子类化作为副作用来抑制。
在java8中,有更多设计可供考虑 -
具有所有静态方法的接口 - 这与具有所有静态方法的类一样好。接口和类都没有为此目的而设计,因此任何一个都可以。但是,不要指望在接口的子类型中继承这些静态方法 - 接口静态方法不可继承。使用接口的一个优点是我们不需要抑制默认构造函数出现在javadoc上。
具有所有默认方法的接口 - 通过继承访问。这很有趣,但总的来说有问题(继承仅适用于非静态上下文)。但在某些API设计中,它可能是更好的选择,例如,这个html builder API。
答案 3 :(得分:1)
如果你只是为其他类提供“工具”的方法,这为什么不是好的做法。
答案 4 :(得分:1)
只有静态方法的类是Java中用于实用程序方法的常见模式。标准库中的示例包括Files,Collections和Executors。
对于这样的实用程序类,确保您的类无法实例化是一个好主意,以使类的意图清晰。您可以通过显式声明私有构造函数来实现。请参阅"有效Java中的Item 4: Enforce noninstantiability with a private constructor"由Josh Bloch提供详情。
答案 5 :(得分:1)
Singleton是好的,具体取决于具体情况。
出于测试目的,您可能想要模拟对单例的引用,以避免在单元测试期间产生副作用。 在这种情况下,使用依赖注入框架(如Spring)来处理实例的创建并使用可以覆盖的常规方法而不是静态方法可能是有意义的。
如果仍计划使用静态方法,请确保在多线程上下文中使用时调用是线程安全的。 (例如,双重检查锁定)。