我正在学习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.为什么旧班仍然会发出警告?波希米亚人我还没有意识到你在帖子中提到的概念。一旦我有了更好的主意,我会回到他们身边。感谢您解释一下。
答案 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
成员。
优良作法是始终将您的课程设为abstract
或final
,这意味着他们只打算 ,或不,继承。很多时候你会设计一个既可以实例化(不抽象)又可以扩展(不是最终)的类,但是这是一个有意识的决定是一个很好的习惯。
答案 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>