我想创建一个未在超类中实现的常量,以强制子类实现它。我发现(关于这个主题)的最佳解决方案是创建一个返回常量值的抽象方法。我认为不可能做类似的事情:
abstract final static String Name;
但我仍然抱有希望,因为 Java 在带有 serialVersionUID的Serializable 接口中使用了类似的东西。有人知道他们是怎么做到的吗?是否可以在我自己的课堂上重现它?
我想创建一个未在超类中实现的常量,以强制子类实现它。我发现(关于这个主题)的最佳解决方案是创建一个返回常量值的抽象方法。我认为不可能做类似的事情:
abstract final static String Name;
但我仍然抱有希望,因为 Java 在带有 serialVersionUID的Serializable 接口中使用了类似的东西。有人知道他们是怎么做到的吗?是否可以在我自己的课堂上重现它?
这样的常量不可能是static因为static字段在类的所有实例之间共享,包括所有子类的实例。以下是如何将其实现为非静态常量:
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不是Serializable接口的一部分。
serialVersionUID接口不强制字段存在,Serializable因为接口不能强制存在字段。您可以声明一个实现的类,它可以在没有字段的Serializable情况下编译得很好。serialVersionUID
检查serialVersionUID字段在工具中是硬编码的。一个例子是 使用反射java.io.ObjectStreamClass.getSerialVersionUID()加载值的 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;
}
我不推荐它,但如果你非常需要它,你可以在Checkstyle中创建一个正则表达式检查并强制人们实现静态变量
当实现的类Serializable没有serialVersionUID您在 IDE 中看到的小消息并且在编译时是由javac. 如果你想创建类似的东西,你可以,但过程似乎很复杂。解决方案就在这个答案中。
它们进行了详细介绍,但总体思路是创建注释和注释处理器,并在编译期间使用注释处理器。我猜你可以使用反射(或者......不是反射,因为它是编译时间?)来查看带注释的类是否包含你想要的字段。
这是我发现模拟它的最佳方法。Javadoc 防止防止有点糟糕的扩展......但 id 子类没有 NAME 它只会无法执行
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";
}