Абстрактная константа в Java

Я хотел бы создать константу, не реализованную в суперклассе, чтобы заставить подклассы реализовать ее. Лучшее решение, которое я нашел (по этой теме) - создать абстрактный метод, который будет возвращать постоянное значение. Я предполагаю, что невозможно сделать что-то вроде:

abstract final static String Name;

Но у меня все еще есть надежда, потому что Java использует что-то подобное в Serializable интерфейсе с serialVersionUID. Кто-то знал, как они это сделали? Можно ли воспроизвести это в моем собственном классе?

Ответ 1

Наличие поля serialVersionUID не обеспечивается интерфейсом Serializable поскольку интерфейс не может обеспечить наличие поля. Вы можете объявить класс, который реализует Serializable, он будет прекрасно компилироваться без serialVersionUID поля serialVersionUID.

Проверка поля serialVersionUID жестко задана в инструментах. Одним из примеров является JDK java.io.ObjectStreamClass.getSerialVersionUID() который загружает значение 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;
}

Ответ 2

Такая константа не может быть 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.

Ответ 3

Я бы не рекомендовал это, но если вам это так нужно, вы можете создать проверку регулярных выражений в Checkstyle и заставить людей реализовать статическую переменную

Ответ 4

Когда класс, реализующий Serializable, не имеет serialVersionUID небольшое сообщение, которое вы видите в вашей IDE и во время компиляции, является предупреждением, javac. Если вы хотите создать что-то подобное, вы можете, но процесс кажется сложным. Решение здесь в этом ответе.

Они углубляются в детали, но общая идея состоит в том, чтобы создать процессор аннотаций и аннотаций и использовать процессор аннотаций во время компиляции. Я предполагаю, что вы могли бы использовать отражение (или... не отражение, так как это время компиляции?), Чтобы увидеть, содержит ли аннотированный класс поле, которое вы хотите.

Ответ 5

Здесь лучший способ, который я нашел, чтобы смоделировать это. 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";
}