为什么我在Java中收到有关实用程序类的警告

时间:2011-10-14 10:21:18

标签: java

我正在学习Java和OOPS,在eclipse中编写一个基本的Hello World时,我看到一个黄色三角形告诉我'实用程序类不应该有公共或默认构造函数'。我无法理解为什么会发生这种情况,这是什么意思?我做错了什么?

class HelloWorld {


public static void main(String[] args)
{
    // TODO Auto-generated method stub
            System.out.println("Hola Mundo!");

}


  }

EDIT1:编辑代码以包含建议的更改。

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:

创建了一个新类,现在它可以工作了。谢谢Jon.为什么旧班仍然会发出警告?波希米亚人我还没有意识到你在帖子中提到的概念。一旦我有了更好的主意,我会回到他们身边。感谢您解释一下。

6 个答案:

答案 0 :(得分:57)

这意味着有人可以写:

HelloWorld helloWorld = new HelloWorld();

当你可能不希望他们这样做时 - 你没有提供任何实例成员,那么为什么要允许他们创建实例呢?将代码重写为:

final class HelloWorld {

    private HelloWorld() {
        // Prevent instantiation
        // Optional: throw an exception e.g. AssertionError
        // if this ever *is* called
    }

    public static void main(String[] args) {
        System.out.println("Hola Mundo!");
    }
}

答案 1 :(得分:17)

Jon说了什么,但你也应该知道每个类都有一个构造函数,无论你是否声明了一个。如果你没有声明一个,那么默认为你定义“默认构造函数”。

换句话说,这两个类的行为相同:

public class ClassA {
}


public class ClassB {
    public ClassB() {
    }
}

警告:拥有私有构造函数不会阻止实例化!

而且只是为了肛门,有一个私人构造函数阻止某人实例化你的类,它只会让它变得更难:

有(至少)两种方法来解决它:

声明一种工厂方法(很明显,但如果这是你公司的代码,有人可以这样做):

public class ClassA {
    private ClassA() {}

    public static ClassA create() {
        return new ClassA(); // oops! this one got away
    }
}


使用反射(鬼鬼祟祟,似乎有点错误,但它有效!):

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!

保证没有人创建实例的唯一方法是在(也可能使其成为私有)构造函数中抛出异常。

答案 2 :(得分:8)

为了完整起见,到目前为止,没有一个响应者对你的原始课程的另一个问题发表了评论

class HelloWorld {

正如建议的那样,你变成了

final class HelloWorld {

Java类上的final关键字禁止其他类扩展(继承)它。如果你没有让一个类最终,扩展类可以使用你可能没有预期的各种事情,因为扩展类可以访问继承类的protected成员。

优良作法是始终将您的课程设为abstractfinal,这意味着他们只打算 ,或,继承。很多时候你会设计一个既可以实例化(不抽象)又可以扩展(不是最终)的类,但是这是一个有意识的决定是一个很好的习惯。

答案 3 :(得分:5)

编写实用程序类的最简单方法是使用没有实例的枚举。您可以使用Java 5.0及更高版本。

public enum Utility {;
    public static void main(String... args) {
        System.out.println("Hola Mundo!");
    }
}

您不必定义私有构造函数,也不能使用内部类或其他技巧(如反射)创建实例。 (如果忽略Unsafe类;)

顺便说一句:有些人认为使用enum作为黑客,但对我来说它明确地说“我有一个没有实例的类”,而不是阻止创建间接的实例。

答案 4 :(得分:2)

看看这个:http://checkstyle.sourceforge.net/config_design.html#HideUtilityClassConstructor
我假设你正在使用CheckStyle。

答案 5 :(得分:0)

对于Spring应用程序,请尝试以下操作:

创建一个禁止检查文件checkstyle-suppressions.xml

的配置文件
 <?xml version="1.0"?>

<!DOCTYPE suppressions PUBLIC
        "-//Puppy Crawl//DTD Suppressions 1.0//EN"
        "http://www.puppycrawl.com/dtds/suppressions_1_0.dtd">

<suppressions>
    <suppress files="SpringBootApplication.java" checks="HideUtilityClassConstructor" />
</suppressions>

maven-checkstyle-plugin插件配置中,添加checkstyle-suppressions.xml

的位置
    <configuration>
        <configLocation>quality/checkstyle.xml</configLocation>
        <suppressionsLocation>quality/checkstyle-suppressions.xml</suppressionsLocation>