Java 最佳实践:仅使用静态方法的类
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31409982/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java best practice: Class with only static methods
提问by user3629892
I have an application where I have a class called PlausibilityChecker
. This class has only static methods, like checkZipcodeFormat
or checkMailFormat
. I use them in my GUI classes to check the input before sending it to the lower layer.
我有一个应用程序,其中有一个名为PlausibilityChecker
. 这个类只有静态方法,比如checkZipcodeFormat
or checkMailFormat
。我在 GUI 类中使用它们来检查输入,然后再将其发送到下层。
Is this good practice? I thought I'd go with only static methods so that I don't have to care about passing an instance to the GUI classes or having an instance field in each gui class that doesn't reference a gui object.
这是好的做法吗?我以为我只使用静态方法,这样我就不必关心将实例传递给 GUI 类,或者在每个 gui 类中都有一个不引用 gui 对象的实例字段。
I noticed that the Files
class of Java NIO
has only static methods so I assume this can't be that horribly wrong.
我注意到Files
类Java NIO
只有静态方法,所以我认为这不会是那么可怕的错误。
采纳答案by Luiggi Mendoza
I would say you're doing it right. Apart of that, some advices for your utility class:
我会说你做得对。除此之外,还有一些对您的实用程序类的建议:
- Make sure it doesn't have any state. This is, there's no field in the class unless it's declared
static final
. Also, make sure this field is immutable as well e.g.String
s. - Make sure it cannot be a super class of other classes. Make the class
final
so other programmers cannot extend it. - This one is debatable, but you may declare a no-arg constructor
private
, so no other class could create an instance of your utility class (using reflection or something similar will do, but there's no need to go that protective with the class). Why you may not do this? Well, this is the strange case where you want/need to inject an instance of the utility class e.g. through an interface rather than directly using it along your class. Here's an example of this. This design is really odd but may happen (as shown in the link above), but if you will not run in such case, the best advice is to keep the constructorprivate
.
- 确保它没有任何状态。也就是说,类中没有字段,除非它被声明
static final
。另外,请确保该字段也是不可变的,例如String
s。 - 确保它不能是其他类的超类。制作该类,
final
以便其他程序员无法扩展它。 - 这个是有争议的,但你可以声明一个无参数的构造函数
private
,所以没有其他类可以创建你的实用程序类的实例(使用反射或类似的东西可以做,但没有必要对类进行保护)。为什么你不能这样做?嗯,这是一种奇怪的情况,您想要/需要注入实用程序类的实例,例如通过接口而不是直接在您的类中使用它。这是一个例子。这种设计确实很奇怪,但可能会发生(如上面的链接所示),但如果您不会在这种情况下运行,最好的建议是保留构造函数private
。
There are lot of libraries that provide utility classes in order to help us programmers with our work. One of the most known is Apache Commonset of libraries. It's open source and you can check the code to see how they design these utility classes in order to create yours. (DISCLAIMER: I do not work or support these libraries, I'm a happy user of them)
有很多库提供实用程序类以帮助我们程序员完成我们的工作。最著名的一个是Apache Common库集。它是开源的,您可以检查代码以了解它们如何设计这些实用程序类以创建您的实用程序类。(免责声明:我不工作或不支持这些库,我是它们的快乐用户)
Important Note: Avoid using a singleton for your utility class.
重要提示:避免在您的实用程序类中使用单例。
回答by Exar666Kun
Why should it not be good practice if you just have methods which provides "tools" to other classes this is fine.
如果您只有为其他类提供“工具”的方法,为什么这不是好的做法,这很好。
回答by markusk
Classes with only static methods is a common pattern in Java for utility methods. Examples in the standard library include Files, Collections, and Executors.
只有静态方法的类是 Java 中实用方法的常见模式。标准库中的示例包括Files、Collections和Executors。
For such utility classes, it's a good idea to make sure that your class cannot be instantiated, to make the intent of the class clear. You can do so by explicitly declaring a private constructor. See Item 4: Enforce noninstantiability with a private constructorin "Effective Java" by Josh Bloch for details.
对于此类实用程序类,最好确保您的类不能被实例化,以明确类的意图。您可以通过显式声明私有构造函数来实现。有关详细信息,请参阅Josh Bloch撰写的“Effective Java”中的条款4:使用私有构造函数强制不可实例化。
回答by Jin Kim
Singleton are ok, depending on the context.
单例没问题,具体取决于上下文。
For testing purposes, you may want to mock out references to singletons to avoid side effects during unit tests. In that case, it probably makes sense to use a dependency injection framework such as Spring to handle the creation of the instance and use regular methods which can be overridden instead of static methods.
出于测试目的,您可能希望模拟对单例的引用,以避免在单元测试期间产生副作用。在这种情况下,使用依赖注入框架(例如 Spring)来处理实例的创建并使用可以覆盖的常规方法而不是静态方法可能是有意义的。
If you still plan to use static methods, ensure that the calls are thread-safe if used in a multi-threaded context. (e.g. double-checked locking).
如果您仍计划使用静态方法,请确保在多线程上下文中使用时调用是线程安全的。(例如双重检查锁定)。
回答by ZhongYu
Don't worry about subclassing or instantiation. The following utility classes in JDK can be subclassed or instantiated, yet nobody has misused them in all those years. People are not thatstupid.
不要担心子类化或实例化。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
However, as a public API, you do want to suppress the default constructor, otherwise there is an undocumented constructor on the javadoc page which is awkward and confusing. For your own in-house APIs, it doesn't matter, nobody cares.
但是,作为公共 API,您确实希望取消默认构造函数,否则 javadoc 页面上有一个未记录的构造函数,这很尴尬且令人困惑。对于您自己的内部 API,这无关紧要,没人关心。
There is no reason to suppress subclassing though. If anyone wants to subclass a utility class, for whatever reason, let him. Of course, private constructor will suppress subclassing as a side effect.
但是没有理由抑制子类化。如果有人想继承一个实用程序类,无论出于何种原因,让他。当然,私有构造函数将抑制子类化作为副作用。
In java8, there are more design possibilities to consider -
在 java8 中,有更多的设计可能性需要考虑——
An interface with all static methods- this is just as good as a class with all static methods. Neither interface nor class is designed for this purpose, so either one is OK. However, don't expect to inherit these static methods in subtypes of the interface - interface static methods are not inheritable. One plus point for using interface is that we don't need to suppress the default constructor from appearing on javadoc.
具有所有静态方法的接口- 这与具有所有静态方法的类一样好。接口和类都不是为此目的而设计的,所以任何一个都可以。但是,不要期望在接口的子类型中继承这些静态方法——接口静态方法是不可继承的。使用 interface 的一个优点是我们不需要禁止默认构造函数出现在 javadoc 中。
An interface with all default methods- accessed through inheritance. This is interesting but problematic in general (the inheritance works only in non-static context). But it might be a better option in some API designs, for example, this html builderAPI.
具有所有默认方法的接口- 通过继承访问。这很有趣,但通常有问题(继承仅在非静态上下文中有效)。但是在某些 API 设计中它可能是更好的选择,例如这个html builderAPI。
回答by afenkner
In Java 8 you can now change your static utility classes to interfaces with static implementations. This eliminates the need for making the class final and having to provide a private constructor. It's as simple as changing 'class' to 'interface' and removing the final word if you have it (all interfaces are abstract so they cannot be final). Since interface methods are always public you can remove any public scope from them. If you have a private constructor then remove that as well (you can't compile an interface with a constructor since they can't be instantiated). It's less code and looks cleaner. You won't have to refactor any classes that already use it.
在 Java 8 中,您现在可以将静态实用程序类更改为具有静态实现的接口。这消除了使类成为 final 和必须提供私有构造函数的需要。就像将“类”更改为“接口”并删除最终单词一样简单(所有接口都是抽象的,因此它们不能是最终的)。由于接口方法始终是公共的,因此您可以从中删除任何公共范围。如果你有一个私有构造函数,那么也删除它(你不能用构造函数编译接口,因为它们不能被实例化)。它的代码更少,看起来更干净。您不必重构任何已经使用它的类。