当我需要一堆无状态实用程序方法时,Java 8中的最佳实践是什么。拥有一个不的界面是正确的,即public interface Signatures
和public interface Environments
,或者以旧的方式做得更好 - 拥有{{1} }和public final class Signatures
私有构造函数||枚举?
答案 0 :(得分:28)
接口的主要目的是提供该类型的操作(方法)的类型和词汇表。它们是有用且灵活的,因为它们允许多个实现,实际上它们被设计为允许在类层次结构中不相关的实现。
问题是,
拥有一个不会被任何人实现的界面是对的吗??
在我看来,这样可以减少对接口的影响。人们必须环顾API以确定没有实现此接口的类,并且没有此接口的生产者或使用者。有人可能会感到困惑,并试图创建一个接口的实现,但当然他们不会走得太远。虽然可以使用所有静态方法的“实用程序接口”,但这并不像旧的不可构造的最终类成语那样清晰。后者的优点是类可以强制执行,不会创建任何实例。
如果你看一下新的Java 8 API,你会看到尽管能够在接口上添加静态方法,仍然会使用最终的类习惯用法。
接口上的静态方法已用于诸如工厂方法之类的东西,以创建这些接口的实例,或者用于在这些接口的所有实例中具有普遍适用性的实用程序方法。例如,请参阅Stream
中的Collector
和java.util.stream
接口。每个都有静态工厂:Stream.of()
,Stream.empty()
和Collector.of()
。
但请注意,每个都有伴随工具类StreamSupport
和Collectors
。这些是纯实用程序类,仅包含静态方法。可以说它们可以合并到相应的接口中,但这会使接口混乱,并且会模糊类中包含的方法的关系。例如,StreamSupport
包含一系列相关的静态方法,这些方法都是Spliterator
和Stream
之间的所有适配器。将这些合并到Stream
可能会让事情变得混乱。
答案 1 :(得分:6)
我会使用最后一堂课。更好地告诉我它是一个带有一些实用方法的辅助类。接口定义是我期望实现的东西,以及帮助某人实现接口的方法。
答案 2 :(得分:2)
接口中的静态方法添加了两个主要目的:
如果子类中实现不良,可以使用静态接口方法提供检查(例如,如果值为null)。
避免使用通用实用程序类(如Collections
)并通过适当的接口调用静态方法。
因此,如果您打算与相应的类共享功能,那么这是一个非常好的做法。
更新:
如果您希望构建纯函数集合,那么您可能希望将抽象类与静态方法和私有构造函数一起使用。
答案 3 :(得分:2)
在良好的面向对象设计中,没有很多(如果有的话)无状态实用方法。
我要处理的最好的技巧是使用状态(对象)来处理函数。
所以不要做
Temperature.farenheitFromCelcius(...);
我做
public class FarenheitFromCelcius implements Function<Celcius, Farenheit> {
public Farenheit apply(Celcius celcius) {
return new Farenheit(5 * celcius.getValue() / 9 + 32);
}
}
这有一些优点。一个是它可以更容易地从内存中卸载。另一个是你可以节省类型识别接口的数量,你可以在方法之间传递实用程序方法,最后可以利用Java类型层次结构。
成本极低。基本上你必须改变方法的应用方式。
public <T> R convertTemp(T temp, Function<T, R> conversion) {
return conversion.apply(temp);
}
当然,你永远不会编写一个完整的方法来封装面向对象的函数,但我必须展示一个例子...
答案 4 :(得分:0)
在您的情况下,我会上最后一堂课,而不是因为某人可能会实施或固有的this
而感到疲劳。对于需要静态util接口的用例。我想我们需要一个最终接口...
public final class Util {
private Util {
throw new AssertionError("Please don't invoke me");
}
public static someUtilMethod() {}
private static someHelperUtilMethod() {}
}