我有一个非常简单的问题:
我想要一个Java类,它提供了一个公共静态方法,它可以做一些事情。这仅用于封装目的(在一个单独的类中包含所有内容)...
此类既不应实例化,也不应扩展。这让我写道:
final abstract class MyClass {
static void myMethod() {
...
}
... // More private methods and fields...
}
(虽然我知道,这是禁止的。)
我也知道,我可以使这个类完全是final,并覆盖标准构造函数,同时将其设为私有。
但在我看来,这更像是一种“解决方法”,并且应该更有可能通过最终的抽象类来完成......
我讨厌变通方法。所以只是为了我自己的利益:还有另一种更好的方法吗?
答案 0 :(得分:50)
比使用没有实例的enum
简单得多。
public enum MyLib {;
public static void myHelperMethod() { }
}
这个类是final的,显式没有实例和私有构造函数。
这是由编译器检测到的,而不是运行时错误。 (与抛出异常不同)
答案 1 :(得分:45)
参考:有效的Java第2版第4项“使用私有构造函数强制实现非实例化”
public final class MyClass { //final not required but clearly states intention
//private default constructor ==> can't be instantiated
//side effect: class is final because it can't be subclassed:
//super() can't be called from subclasses
private MyClass() {
throw new AssertionError()
}
//...
public static void doSomething() {}
}
答案 2 :(得分:6)
不,你应该做的是创建一个私有空构造函数,在它的主体中抛出异常。 Java是一种面向对象的语言,一个永远不会被实例化的类本身就是一种解决方法! :)
final class MyLib{
private MyLib(){
throw new IllegalStateException( "Do not instantiate this class." );
}
// static methods go here
}
答案 3 :(得分:4)
不,抽象类是要扩展的。使用私有构造函数,它不是一种解决方法 - 它是这样做的方法!
答案 4 :(得分:2)
将类的构造函数声明为private
。这确保了不可实现性并阻止了子类化。
答案 5 :(得分:1)
assylias(所有Java版本)和Peter Lawrey(> = Java5)的建议是这种情况下的标准方法。
但是我想提醒你注意,防止静态实用程序类的扩展是一个非常最终的决定,当你发现在不同的项目中你有相关的功能而你可能会在以后困扰你。事实上,我想扩展它。
我建议如下:
public abstract MyClass {
protected MyClass() {
}
abstract void noInstancesPlease();
void myMethod() {
...
}
... // More private methods and fields...
}
这是反对已建立的实践,因为它允许在需要时扩展类,它仍然可以防止意外实例化(甚至无法创建匿名子类实例而不会得到非常清晰的编译器错误)。
总是 pisses 我JDK的实用程序类(例如java.util.Arrays)实际上是最终的。如果你想拥有自己的Arrays类和方法来比较,你就不能,你必须创建一个单独的类。这将分发(IMO)所属的功能,并且应该通过一个类提供。这使您无法使用分布式实用方法,或者您必须将每个方法复制到您自己的类中。
我建议永远不要让这样的实用程序类最终。在我看来,这些优点并没有减轻它们的劣势。
答案 6 :(得分:0)
您不能将课程标记为抽象和最终。他们几乎相反 含义。抽象类必须是子类,而最终类不能是子类 子类。如果您看到用于类或方法声明的抽象和最终修饰符的组合,则代码将无法编译。
答案 7 :(得分:-1)
这是一个非常简单的解释,简单的英语。抽象类无法实例化,只能扩展。最终的类不能扩展。现在如果你创建一个抽象类作为最终类,你怎么认为&#39我将永远使用那个课程,实际上,首先是把自己置于这样一个陷阱的理由是什么?
答案 8 :(得分:-2)