java中的抽象常量
我想创建一个未在超类中实现的常量,以便强制子类实现它。我发现()的最佳解决方案是创建一个将返回常量值的抽象方法。我认为这样做是不可能的:java中的抽象常量,java,Java,我想创建一个未在超类中实现的常量,以便强制子类实现它。我发现()的最佳解决方案是创建一个将返回常量值的抽象方法。我认为这样做是不可能的: abstract final static String Name; 但我仍然有希望,因为Java在serialVersionUID中使用了类似的东西。有人知道他们是怎么做到的吗?是否可以在我自己的类中复制它?serialVersionUID接口不强制字段存在,因为接口不能强制字段存在。您可以声明一个实现了Serializable的类,它可以在没有seria
abstract final static String Name;
但我仍然有希望,因为Java在serialVersionUID中使用了类似的东西。有人知道他们是怎么做到的吗?是否可以在我自己的类中复制它?
serialVersionUID
接口不强制字段存在,因为接口不能强制字段存在。您可以声明一个实现了Serializable
的类,它可以在没有serialVersionUID
字段的情况下正常编译
检查serialVersionUID
字段在工具中是硬编码的。一个例子是JDK方法,它加载带有反射的serialVersionUID
值:
/**
* Returns explicit serial version UID value declared by given class, or
* null if none.
*/
private static Long getDeclaredSUID(Class<?> cl) {
try {
Field f = cl.getDeclaredField("serialVersionUID");
int mask = Modifier.STATIC | Modifier.FINAL;
if ((f.getModifiers() & mask) == mask) {
f.setAccessible(true);
return Long.valueOf(f.getLong(null));
}
} catch (Exception ex) {
}
return null;
}
/**
*返回给定类声明的显式串行版本UID值,或
*如果没有,则为null。
*/
私有静态长getDeclaredSUID(类别cl){
试一试{
字段f=cl.getDeclaredField(“serialVersionUID”);
int mask=Modifier.STATIC | Modifier.FINAL;
if((f.getModifiers()&掩码)=掩码){
f、 setAccessible(true);
返回Long.valueOf(f.getLong(null));
}
}捕获(例外情况除外){
}
返回null;
}
此类常量不能是静态的
,因为静态的
字段在类的所有实例之间共享,包括所有子类的实例。
以下是如何将其实现为非静态常量:
public abstract class Foo {
public final String name; // Particular value to be defined in subclass
protected Foo (String name) {
this.name = name;
}
}
public class Bar extends Foo {
public Bar () {
super ("Zoo"); // Here we define particular value for the constant
}
}
顺便说一句,
serialVersionUID
不是可序列化接口的一部分。我不推荐它,但如果您非常需要它,您可以创建一个regex签入并强制人们实现静态变量,这是我发现的模拟静态变量的最佳方法。Javadoc阻止一点到坏的扩展。。。但是id子类没有名称,它将无法执行
public abstract class Foo {
protected final String NAME;
public Foo() {
String name="";
try {
name = (String) this.getClass().getDeclaredField("NAME").get(name);
} catch (NoSuchFieldException
| SecurityException
| IllegalArgumentException
| IllegalAccessException e) {
e.printStackTrace();
}
NAME = name;
}
}
public class Bar extends Foo {
public static final String NAME = "myName";
}
当实现
Serializable
的类没有serialVersionUID
时,您在IDE中看到的小消息以及编译时是由javac
发出的警告。如果你想创造这样的东西,你可以,但过程似乎很复杂。解决办法就在这里
它们非常详细,但总体思路是创建注释和注释处理器,并在编译期间使用注释处理器。我猜您可以使用反射(或者…不是反射,因为它是编译时?)来查看带注释的类是否包含所需的字段。问题是如何使用serialVersionUID解决这个问题?所以这是有可能的……仅供参考,在可序列化的情况下,运行时需要的是
serialVersionUID
,而不是编译器。实现了Serializable
且没有该字段的类可以很好地编译。此外,serialVersionUID
对于运行时也不是必需的。如果它不存在,序列化机制会计算它。即使它不是强制性的,它仍然会请求它。SerialVersionUID不是我想要的确切解决方案,但它非常接近。@JulienMaret如果它不存在,您是否更关心发出警告,或者如果它不存在,您是否希望获得默认值?或者两者都有?你确定代码不会编译吗?您的代码看起来不仅可以编译,而且运行时不会出错,因为您捕获了异常?我想您应该在catch块中将NAME
设置为Foo.NAME
,对吗?这样,如果他们不“覆盖”它,它将使用“默认值”?为什么要将name
引用的空字符串
传递给(子)类声明的get
方法?这显然不是这次行动的正确目标。当你检查了NAME
是否存在时,你从中得到了什么?您是否知道,当您创建Bar
的子类时,此代码将中断?@JulienMaret Checkstyle不仅仅是一个Eclipse插件。它也可以像Maven一样成为构建过程的一部分。我认为这不是一个好的解决方案,但我只想指出它实际上不是特定于IDE的。