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

На этот вопрос уже есть ответ здесь:

Какие правила предписывают наследование статических переменных в Java? 3 ответа

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

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();
}

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

Это возможно? И как?

 sidshu18 июн. 2013 г., 16:59
Еще немного информацииstackoverflow.com/questions/9898097/...
 sidshu18 июн. 2013 г., 16:58
Еще несколько деталей в обсуждении:stackoverflow.com/questions/9898097/...

Ответы на вопрос(9)

ID, точка. Поэтому, если вам нужны отдельные счетчики для Sub1 и Sub2, вы объявляете static в каждом из этих классов.

Решение Вопроса

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

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++;
    }

    //...
}

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

 Andreas Fester18 июн. 2013 г., 17:03
@RudolphEst хороший момент - время истекает, но добавлю это к моему ответу
 RudolphEst18 июн. 2013 г., 17:02
Это хороший способ сделать то, что нужно OP, но я думаю, что стоит упомянуть, что использование статических переменных таким образом не является потокобезопасным. Было бы неплохо использовать здесь синглтоны и фабричные методы.

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

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);
}
</class<?>

Осторожно: вышеупомянутое не является поточно-ориентированным Но ваш исходный код нет либо ...

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

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

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

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

У каждого подкласса должен быть свой.static curID

 darijan18 июн. 2013 г., 17:00
Ах хорошо. Извините за поспешный ответ.
 Ingo18 июн. 2013 г., 21:15
Я не'не одобряю, но этоне толькоэкземпляры класса " которые разделяют одну и ту же статическую переменную. Это'Это просто весь код, который может получить доступ к этой переменной.

static переменная

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

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

Так что даже если вы скажете

r1.curID;
t1.curID;

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

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

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

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

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

 user20742121 апр. 2018 г., 05:05
Невозможно переопределить это не то же самое, чтоне наследуется ».
 MGorgon25 сент. 2016 г., 18:44
JLS говорит что-то другое:docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.4.8 Класс C наследует от своего прямого суперкласса все конкретные методы m (как статические, так и экземпляры) суперкласса
 Andrzej Doyle26 сент. 2016 г., 12:25
@MGorgon Это недействительно унаследовать методы - вы можетепереопределить их, и поскольку статические ссылки разрешаются во время компиляции, это неэто даже возможно. Это'больше похоже на псевдоним суперкласса метод (я согласен, что JLS ' язык вводит в заблуждение). Кроме того, проблема здесь неt с методами, но с полями - поведение связано с тем, что оба подкласса ссылаются на одно и то жеcurID Поле «.

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

 Eugene24 апр. 2018 г., 15:31
@ LuiggiMendoza это неправильно, ониявляются наследуется, ноне переопределение
 Luiggi Mendoza24 апр. 2018 г., 16:25
@ Евгений исправил ...
 Eugene24 апр. 2018 г., 21:29
@LuiggiMendoza не очень уверен в этомтак как они принадлежат к классу, который объявляет их правильно, наследование означает, что они принадлежат к классу, который наследует их ... О сокрытии, вы могли бы избежать этого, объявив егоfinal в родительском классе, но тогда ошибка от компилятора просто очень странная
 Luiggi Mendoza25 сент. 2016 г., 18:47
@MGorgon JLS означает, что подклассы будут иметь этот метод, но не могут быть переопределены, так как являются статическими, что практически совпадает с тем, что метод не наследуется, это больше похоже на навязывание метода.
 user20742121 апр. 2018 г., 05:05
Невозможно переопределить это не то же самое, чтоне наследуется ».
 MGorgon25 сент. 2016 г., 19:28
Я согласен с вами, но формально JLS строго указывает, что статические методы наследуются. Это'Это немного сбивает с толку, но ваш ответ в сертификации оракула будет неверным.
 MGorgon25 сент. 2016 г., 18:43
JLS говорит что-то другое:docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.4.8  Класс C наследует от своего прямого суперкласса все конкретные методы m (как статические, так и экземпляры) суперкласса
 Luiggi Mendoza08 февр. 2018 г., 16:10
@MGorgon они 'не наследуется. Фактически, вы не можете переопределить это, но вы можете скрыть это в подклассах.

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

Ваш ответ на вопрос