Есть ли в java поле Readonly (которое настраивается в рамках самого класса)? - PullRequest
34 голосов
/ 16 ноября 2011

Как мы можем иметь переменную, доступную для записи внутри класса, но только "читаемую" вне его?

Например, вместо того, чтобы делать это:

Class C {
  private int width, height;

  int GetWidth(){
    return width;
  }

  int GetHeight(){
    return height;
  }

  // etc..

Я бы хотел сделать что-то вроде этого:

Class C {
  public_readonly int width, height;

  // etc...

Какое лучшее решение?

Ответы [ 7 ]

40 голосов
/ 20 февраля 2014

Создать класс с полями public final.Укажите конструктор, где эти поля будут инициализированы.Таким образом, ваш класс будет неизменным, но у вас не будет лишних затрат на доступ к значениям извнеНапример:

public class ShortCalendar
{
    public final int year, month, day;

    public ShortCalendar(Calendar calendar)
    {
        if (null == calendar)
            throw new IllegalArgumentException();

        year = calendar.get(Calendar.YEAR);
        month = calendar.get(Calendar.MONTH);
        day = calendar.get(Calendar.DATE);
    }
}
17 голосов
/ 16 ноября 2011

Нет никакого способа сделать это в Java.

Два ваших варианта (один из которых вы упомянули) - использование открытых методов получения и закрытие поля или полная документация в классе.

Накладные расходы на методы получения очень малы (если вообще).Если вы делаете это большое количество раз, вы можете захотеть кэшировать извлеченное значение вместо вызова метода get.

EDIT:

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

6 голосов
/ 16 ноября 2011

из того, что я знаю, компилятор не оптимизирует этот вид кода

JIT-компилятор Hotspot определенно делает .

Мне было интересно, какое решение лучше?

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

3 голосов
/ 16 ноября 2011

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

1 голос
/ 16 ноября 2011

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

EDIT

Если вам действительно нужен каждый цикл ЦП, используйте C или C ++ (или запишите в него критичные к производительности части и вызовите его через JNA, хотя вряд ли это будет стоить потраченного времени).

0 голосов
/ 07 июля 2018

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

Пример: public final int id = 10;

0 голосов
/ 16 ноября 2011

Ваше решение: частные поля, частные сеттеры, Защищенные или общедоступные методы получения (примечание: защищенный позволяет доступ как из одного пакета, так и из подклассов)

...