Подтвердить что ты не робот

Объявить конечную переменную, но установить позже.

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

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

private final long mId;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    mId = getIntent().getLongExtra(ID_KEY, -1);
}

Я должен указать, что это код Android. Спасибо за помощь. Меня не волнуют геттеры или сеттеры или кто-то меняет мой код. Причина, по которой я спрашивал, - это будущее подтверждение моего кода для следующего разработчика. Я нашел этот пост, который также помогает пролить свет. Android - Activity Constructor vs onCreate

4b9b3361

Ответ 1

Вы можете установить переменную final только в конструкторе или в инициализаторе. Регулярные методы не могут изменить значение объявленных переменных final.

Ответ 2

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


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

class LazyImmutableLong {

    private Long value;

    public void setValue(long value) {
         if (this.value != null) {
             return; // the value has already been set
         }
         this.value = value;
    }
    public long getValue() {return value;}
}

И в вашей деятельности

private LazyImmutableLong id = new LazyImmutableLong();

public void onCreate(..) {
    id.setValue(..);
}

Ответ 3

В этом сценарии может помочь следующий класс Worm (Write-Once-Read-Many).

Мы могли бы создать вложенный класс Wrapper, в котором хранится конечная переменная, в которой вы нуждаетесь. Чтобы инициализировать эту переменную, вы должны просто вызвать конструктор объекта Wrapper. Когда вы вызываете метод getData(), вы получите ссылку на конечную переменную в случае ее инициализации, иначе вы получите null.

Методы getData() и setData(T data) должны быть потокобезопасными. Чтобы обеспечить его, мы используем модификатор volatile для объекта Wrapper. Считывание изменчивой переменной синхронизируется, и запись в изменчивую переменную также синхронизируется. Несмотря на то, что были предприняты некоторые усилия для обеспечения безопасности этого кода, я не тестировал его в этом отношении. В зависимости от уровня безопасности потоков, вы можете рассмотреть возможность синхронизации сеттера и геттера.

public class Worm<T> {
    private volatile Wrapper<T> wrapper;

    public Worm() {}
    public Worm(T data) throws IllegalAccessError
    {
        setData(data);
    }

    public T getData()
    {
        if (wrapper == null)
            return null;
        return wrapper.data;
    }

    public void setData(T data) throws IllegalAccessError
    {
        if (wrapper != null)
            throw new IllegalAccessError();
        else
            wrapper = this.new Wrapper<>(data);
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final Worm<T> other = (Worm<T>) obj;
        return Objects.equals(this.getData(), other.getData());
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(this.getData());
    }

    final private class Wrapper<T> {
        final private T data;

        Wrapper(T data) {
            this.data = data;
        }
    }
}

Ответ 4

private final long mId;

final ссылка не может быть изменена во время выполнения согласно спецификации java. Таким образом, как только вы объявили его окончательным, mId не может указывать на что-то еще на протяжении всего своего жизненного цикла (если вы не используете отражение (или), не переносите значение в объект и не изменяете его через другую ссылку).

Ответ 5

Нет, это невозможно сделать

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

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

Ответ 6

Вы можете установить более позднюю глобальную конечную переменную только в свой конструктор. Пример:

public class ClassA {
   private final long mID;

   public ClassA(final long mID) {
      this.mID = mID;
   }
}

В этом случае в каждом конструкторе вы должны инициализировать конечную переменную.

Ответ 7

вам нужно инициализировать конструктор, как только вы его создадите, или вы можете инициализировать его в max, в конструкторе. Не позднее этого..