Java и унаследованные статические члены

Предположим, что у меня есть класс ниже:

class Parent
{
    private int ID;
    private static int curID = 0;

    Parent()
    {
         ID = curID;
         curID++;
    }
}

и эти два подкласса:

class Sub1 extends Parent
{
    //...
}

и

class Sub2 extends Parent
{
    //...
}

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

Итак, если я это сделаю:

{
    Sub1 r1 = new Sub1(), r2 = new Sub1(), r3 = new Sub1();
    Sub2 t1 = new Sub2(), t2 = new Sub2(), t3 = new Sub2();
}

ID r1, r2, r3 будет 0,1,2, а t1, t2, t3 - 3,4,5. Вместо них я хочу, чтобы t1, t2, t3 имели значения 0,1,2, то есть использовали другую копию статической переменной curID.

Возможно ли это? И как?

Ответ 1

Как уже писали другие, статические члены привязаны к классу, поэтому вам нужно отслеживать идентификатор на уровне класса, например. например:

abstract class Parent {
    private int ID;

    Parent() {
         ID = nextId();
    }

    abstract protected int nextId();
}

class Sub1 extends Parent {
    private static int curID = 0;

    protected int nextId() {
       return curID++;
    }

    //...
}

class Sub2 extends Parent {
    private static int curID = 0;

    protected int nextId() {
       return curID++;
    }

    //...
}

Обратите внимание, что этот подход не является потокобезопасным - но ни один из них не был в этом вопросе. Вы не должны создавать новые объекты из одного и того же подкласса одновременно из разных потоков.

Ответ 2

static поля/методы не наследуются. Они относятся к классу, а не к объектным ссылкам.

Ответ 3

Возможно, но не используя один счетчик. Вам понадобится счетчик для каждого подтипа. Например, что-то вроде следующего:

private static Map<Class<?>, Integer> counters = new HashMap<>();

Parent() {
     Integer curID = counters.get(this.getClass());
     if (curID == null) {
         curID = 0;
     }
     ID = curID;
     curID++;
     counters.put(this.getClass(), curID);
}

Остерегайтесь: приведенное выше не является потокобезопасным. Но ваш исходный код не является...

Ответ 4

Статика - это статика. Существует только один экземпляр curID, период. Поэтому, если вам нужны отдельные счетчики для Sub1 и Sub2, вы объявляете статику в каждом из этих классов.

Ответ 5

Статические элементы вообще не наследуются.

На самом деле нет такой вещи, как Sub1.curID - это законный (но запутанный) способ обращения к Persion.curID.

К сожалению, нет никакого способа сделать то, что вам нужно, со статическими ссылками. Они принципиально не работают и не могут работать с присущим им свойством - поскольку они статически разрешены, они не могут полагаться на динамическую отправку и поэтому не могут зависеть от полиморфизма времени выполнения. Учитывая, что JVM/compiler рассматривает статические переменные таким образом, я уверен, что нет обходного пути, которое вы можете придумать, что позволит вам делать то, что вы хотите.

Если идентификаторы действительно должны быть статичными, тогда вам нужно будет определить разные статические переменные в каждом из подклассов.

Ответ 6

В отличие от других ответов, существует решение вашей проблемы, хотя это не связано с "статическим наследованием". У вас должен быть генератор идентификаторов для каждого класса.

Вот хороший пример:

Java: Родительские методы доступа к статическим переменным подкласса?

Ответ 7

Унаследованный статический член не имеет значения! Статический означает, что он используется всеми экземплярами данного типа.

поскольку Sub1 и Sub2 являются типами Parent, они имеют одинаковое статическое поле.

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

Просьба описать больше того, что вы пытаетесь достичь.

Ответ 8

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

Ответ 9

Члены

static являются частью объекта Parent.class в части PermGen JVM. Все экземпляры этого класса используют одни и те же статические переменные.

Каждый подкласс должен иметь свой собственный static curID.

Ответ 10

Вы используете переменную static

  • Нет копий переменной static для разных объектов,
  • Будет существовать только копия переменной static и она будет использоваться для всех экземпляров

Что касается статического наследования переменных, Они не наследуются вообще

Итак, даже если вы скажете

r1.curID;
t1.curID;

Это будет означать одно и то же, т.е. Parent.curID

Когда вы изменяете переменную static из экземпляра класса, и если другой экземпляр обращается к этой переменной, он получает измененное значение как свою общую переменную