我读了Joshua Bloch的“Effective Java”,并从我们的应用程序中删除了“Constant Interface anti-pattern”。诀窍是使用非实例化的util类,其构造函数是私有的,并将所有常量定义为'public static final'
我必须扩展这个常量util类。我只能在将构造函数更改为protected时才能执行此操作。
有人可以提出更好的方法。
public class Constants {
private Constants () {} // Prevent instantiation
public static final String MyString = "MyString";
}
public class MyConstants extends Constants {
private MyConstants () {} // Compiler error : Implicit super constructor Constants() is not visible.
public static final String MySecondString = "MySecondString";
}
答案 0 :(得分:7)
通常不应该扩展这些常量类。你能否为我们提供一个更具体的例子来说明你想做什么?
通常,您希望在相关时将常量组合在一起,例如,数学常量或特定功能组件的配置参数名称。
如果常量确实相关,那么你是否可以将它们添加到原始类中?或者,您是否有任何理由不能为常量创建单独的类?
答案 1 :(得分:3)
我通常会做以下事情:
public abstract class Constants {
// ...constants...
public Constants () {
throw new UnsupportedOperationException(); // prevent instantiation
}
}
这样可以扩展类以创建派生的实用程序类,但任何(错误的)实例化它的尝试都将失败。我希望以这种方式定义java.util.Collections,因此不必为其他实用程序方法定义Collections2(或类似)。
顺便提一下,给定一个抽象类,“受保护”和“公共”对于构造函数实际上是相同的。仅仅使构造函数受到保护几乎没有任何好处,因为尽管有“保护”,任何人仍然可以轻松地创建类的实例:public class Base {
protected Base() { }
}
// Somewhere else:
Base b = new Base() { }; // anonymous subclass
答案 2 :(得分:2)
我认为将构造函数更改为protected没有任何问题。
我也没有看到使用接口来保持常量有什么问题。
答案 3 :(得分:1)
使用protected
关键字时是否有问题?对我来说,这似乎是一个务实的解决方案。
我必须说(另外)我使用接口来保持常量没有特别的问题。使用static import
使其在您的客户端类中可用。不过,我不会主张实施它。
答案 4 :(得分:1)
如果这些类在同一个包中,并且您想禁止非包类的继承,请考虑使用默认访问:
public class Constants {
Constants () {} // Prevent instantiation
public static final String MyString = "MyString";
}
答案 5 :(得分:0)
我使用Joshua Bloch推荐的方法。
public class Constants {
private Constants() {
throw new AssertionError();
}
public static class Math {
private Math() {
throw new AssertionError();
}
public static final int COUNT = 12;
}
public static class Strings {
private Strings() {
throw new AssertionError();
}
public static final String LOREM = "Lorem";
}
}
Constants
类和嵌套类
如果我需要按类型对常量进行分组,我只会使用嵌套类。请记住,每个嵌套类必须抛出AssertionError
。