为什么我在Java中得到关于实用程序类的警告
我正在学习Java和OOPS,并在Eclipse中编程一个基本的Hello World时,看到一个黄色的三angular形,告诉我“实用程序类不应该有公共或默认的构造函数” 。 我无法理解为什么会发生这种情况,这是什么意思? 我在做什么不对?
class HelloWorld { public static void main(String[] args) { // TODO Auto-generated method stub System.out.println("Hola Mundo!"); } }
编辑1:编辑代码以包含build议的更改。
final class HelloWorld { private HelloWorld() { throw new AssertionError("Instantiating utility class..."); } public static void main(String[] args) { // TODO Auto-generated method stub System.out.println("Hola Mundo!"); } }
仍然收到线路类HelloWorld的警报。
EDIT2:
创build一个新的类,现在它的作品。 谢谢乔恩,老class为什么还要警告呢? 波西米亚我还没有意识到你在文章中提到的概念。 一旦我有了一个更好的主意,我会回到他们身边。 谢谢你解释的事情。
这意味着有人可以写:
HelloWorld helloWorld = new HelloWorld();
当你可能不希望他们 – 你没有提供任何实例成员,那么为什么让他们创build实例? 重写你的代码为:
final class HelloWorld { private HelloWorld() { // Prevent instantiation // Optional: throw an exception eg AssertionError // if this ever *is* called } public static void main(String[] args) { System.out.println("Hola Mundo!"); } }
Jon说了什么,但是你也应该知道每个class级都有一个构造函数,无论你是否声明一个。 如果你没有声明一个,那么默认的构造函数就是为你定义的。
换句话说,这两个类在行为上是相同的:
public class ClassA { } public class ClassB { public ClassB() { } }
注意:有一个私人的构造函数不会阻止实例化!
而只是为了肛门,有一个私人的构造函数不会阻止某人实例化你的类,它只是让它更难:
有(至less)两种方式来解决它:
声明一个工厂方法(很明显,但是如果这是你公司的代码,有人可以这样做):
public class ClassA { private ClassA() {} public static ClassA create() { return new ClassA(); // oops! this one got away } }
使用reflection(鬼鬼祟祟的,似乎错了,但它的工作原理!):
public class ClassA { private ClassA() {} } // Elsewhere, in another class across town: Constructor<?> constructor = ClassA.class.getDeclaredConstructor(); // constructor private? no problem... just make it not private! constructor.setAccessible(true); // muhahahaha Object obj = constructor.newInstance(); System.out.println(obj.getClass().getSimpleName()); // Prints ClassA!
保证没有人创build实例的唯一方法是在一个(也可以使它私有)构造函数中抛出一个exception。
为了保持完整性,迄今没有任何回应者对原来的课程有其他问题进行评论
class HelloWorld {
正如所暗示的那样,你变成了
final class HelloWorld {
Java类的final
关键字禁止其他类扩展(inheritance)。 如果你没有做出最终的类,扩展类可以使用你可能没有想到的各种东西,因为扩展类可以访问inheritance类的protected
成员。
总是让你的课既是abstract
,也是final
,这是好的做法,这意味着他们只是为了或不是为了inheritance。 当你devise一个类可以实例化(不是抽象的)和可扩展的(不是最终的)时,会有很多次,但是做出这个有意识的决定是一个很好的习惯。
写一个实用程序类最简单的方法是你有没有实例的枚举。 你可以用Java 5.0或更高版本来完成。
public enum Utility {; public static void main(String... args) { System.out.println("Hola Mundo!"); } }
您不必定义私有构造函数,也不能使用内部类或reflection等其他技巧创build实例。 (如果您忽略不安全的类;)
顺便说一句:有些人看到使用enum
作为黑客,但对我来说明确地说:“我有一个没有实例的类”,而不是防止创build间接的实例。
看看这个: http : //checkstyle.sourceforge.net/config_design.html#HideUtilityClassConstructor
我假设你正在使用CheckStyle。