Почему в Java нет функции Constant?

Я пытался определить причину констант в Java. Я узнал, что Java позволяет нам объявлять константы с помощью ключевого слова final.

У меня вопрос: почему в Java не появилась функция констант (const). Поскольку многие говорят, что он пришел из C ++, в C ++ есть ключевое слово const.

Пожалуйста, поделитесь своими мыслями.


person gmhk    schedule 29.04.2010    source источник
comment
Есть ключевое слово const, но нет базовой функции. Соответственно исправлены ваш заголовок и теги.   -  person user207421    schedule 07.03.2016


Ответы (8)


Каждый раз, когда я перехожу от тяжелого кода C ++ к Java, мне требуется некоторое время, чтобы приспособиться к отсутствию const-правильность в Java. Это использование const в C ++ сильно отличается от простого объявления постоянных переменных, если вы не знали. По сути, он обеспечивает неизменность объекта при доступе через специальный вид указателя, называемый константным указателем. Когда в Java, в местах, где я обычно хотел бы вернуть константный указатель, я вместо этого возвращаю ссылку с типом интерфейса. содержащие только методы, у которых не должно быть побочных эффектов. К сожалению, это не предусмотрено языком.

Википедия предлагает следующую информацию по этому поводу:

Интересно, что спецификация языка Java рассматривает const как зарезервированное ключевое слово, то есть ключевое слово, которое нельзя использовать в качестве идентификатора переменной, но не присваивает ему семантику. Считается, что ключевое слово было зарезервировано, чтобы позволить расширение языка Java включить методы const в стиле C ++ и указатель на тип const. Билет запроса на расширение в Java Community Process для реализации корректности констант в Java был закрыт в 2005 году, подразумевая, что корректность констант, вероятно, никогда не найдет своего места в официальной спецификации Java.

person Gunslinger47    schedule 29.04.2010
comment
Однако final в Java похожи. - person reinierpost; 20.06.2014
comment
Нет, это не так. final метод, например, работает совершенно иначе, чем методы const C ++. - person dom0; 15.11.2014
comment
@reinierpost Ключевое слово final для свойств или переменных просто гарантирует, что свойство или переменная назначается только один раз. Можно еще изменить состояние этого объекта, например, вызвав какой-нибудь метод с побочными эффектами. final в некоторой степени похож на распределение стека в C ++ с точки зрения ссылки на объект, а не на указатель, но это все. Это, конечно, в дополнение к тому, что уже сказал dom0. - person Tim; 28.03.2016
comment
final в Java, похоже, работает как C ++ const для типов значений, но больше как C ++ non-const T& для ссылочных типов - person Mark K Cowan; 18.08.2016
comment
final - ключевое слово шизофреника. Хотя он предотвращает переназначение, он также используется для закрытия переменных. Я мог бы предотвратить переназначение, но не раскрывать эти переменные, но нет способа сделать это. На мой взгляд, это довольно плохо продуманная языковая функция. - person David Bradley; 12.09.2018
comment
final создает константы времени выполнения, а const создает константы времени компиляции. Другими словами, если мы объявляем поле final, его можно изменить внутри конструктора, если объявлено static final, его можно изменить внутри static initializer block, но если вы хотите, чтобы поле нельзя было изменять после объявления, тогда потребуется const, который в настоящее время недоступен. - person Sisir; 26.12.2018

Что означает const
Во-первых, поймите, что семантика ключевого слова const означает разные вещи для разных людей:

  • ссылка только для чтения - Java final семантика - сама ссылочная переменная не может быть переназначена так, чтобы указывать на другой экземпляр (место в памяти), но сам экземпляр можно изменить
  • ссылка только для чтения - семантика указателя / ссылки C const - означает, что эта ссылка не может использоваться для изменения экземпляра (например, не может назначаться переменным экземпляра, не может вызывать изменяемые методы) - влияет только на ссылочную переменную, поэтому неконстантная ссылка, указывающая на тот же экземпляр, может изменить экземпляр
  • неизменяемый объект - означает, что сам экземпляр не может быть изменен - ​​применяется к экземпляру, поэтому любая неконстантная ссылка не будет разрешена или не может использоваться для изменения экземпляра
  • какая-то комбинация вышеперечисленного?
  • другие?

Почему или почему нет const
Во-вторых, если вы действительно хотите вникнуть в некоторые аргументы «за» и «против», см. обсуждение в рамках этого запроса на улучшение (RFE) «ошибка» . Этот RFE запрашивает функцию "ссылка только для чтения" типа "const". Тема "const", открытая в 1999 году, а затем закрытая / отклоненная Sun в 2005 году, стала предметом бурных дискуссий:

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4211070

Хотя с обеих сторон есть много хороших аргументов, некоторые из часто цитируемых (но не обязательно убедительных или четких) доводов против const включают:

  • может иметь сбивающую с толку семантику, которую можно неправильно использовать и / или злоупотреблять (см. Что означает const выше)
  • может дублировать возможности, доступные в противном случае (например, разработка неизменяемого класса с использованием неизменяемого интерфейса)
  • может возникать нестабильность функций, что приводит к необходимости других семантических изменений, таких как поддержка передачи объектов по значению

Прежде чем кто-либо попытается обсудить со мной хорошие или плохие причины, обратите внимание, что это не мои причины. Они просто являются «сутью» некоторых причин, которые я почерпнул из беглого обзора обсуждения РСЕ. Я не обязательно согласен с ними сам - я просто пытаюсь процитировать, почему некоторые люди (не я) могут подумать, что ключевое слово const не может быть хорошей идеей. Лично мне хотелось бы, чтобы в язык было однозначно введено больше "константной" семантики.

person Bert F    schedule 29.04.2010
comment
+1 только за вторую часть вашего ответа. Многие ключевые слова имеют нетривиальную семантику. volatile так просто понять? Или final? Мех. - person einpoklum; 12.10.2015
comment
OTOH, Java была разработана таким образом, чтобы использовать как можно меньше этих нетривиальных функций. И я не говорю, что они достигли этой цели (или что Java не отошла от этой цели). Но исключение его по этой причине, возможно, все же имело смысл. То, что есть другие сложные вещи, - это еще одна причина не вводить больше (иначе вы в конечном итоге перейдете на язык D). - person Maarten Bodewes; 07.02.2020

const в C ++ не означает, что значение является константой.

const в C ++ подразумевает, что клиент контракта обязуется не изменять его значение.

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

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

eg:

#include <iostream>

int main ()
{
    volatile const int x = 42;

    std::cout << x << std::endl;

    *const_cast<int*>(&x) = 7;

    std::cout << x << std::endl;

    return 0;
}

выводит 42, затем 7.

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

В более сложных системах вы получаете псевдонимы const / non-const без использования const_cast, поэтому привыкание думать, что const означает, что что-то не изменится, становится все более опасным. const просто означает, что ваш код не может изменить его без приведения, а не то, что значение является постоянным.

person Pete Kirkham    schedule 29.04.2010
comment
const int x = 42; - x - постоянная - person ; 29.04.2010
comment
@ Нил, я думаю, он говорит об объектах - person Andy Johnson; 29.04.2010
comment
@andy Аналогично работает с объектами. - person ; 29.04.2010
comment
@Neil Я имел в виду, что когда Пит писал, что const не означает, что значение является постоянным, я понял, что он говорил только о примитивных типах. Чтобы объяснить далее (и я ценю, что вы это знаете): для константной не объектной переменной (скажем, int) компилятор обеспечивает выполнение контракта. Если я объявлю его константным, его нельзя будет изменить. Для объекта я должен объявить как const любые функции-члены, которые изменяют внутреннее состояние объекта. Если я этого не сделаю, то возможно иметь константный экземпляр этого класса, который является (внутренне) изменяемым. Это было моим пониманием того, что он написал. - person Andy Johnson; 29.04.2010
comment
@Neil Если у вас есть один объект или переменная с псевдонимом как константными, так и неконстантными указателями, то значение псевдонима const может быть изменено с помощью псевдонима неконстант. Следовательно, const не означает, что значение является постоянным. Это означает, что клиент значения не может изменять его. В вашем примере нет псевдонима, поэтому все пользователи находятся под одним и тем же ограничением. В общем случае это не так. const влияет на клиентов, а не на ценность - он говорит, что вы не можете его изменить, а не то, что это не изменится. - person Pete Kirkham; 29.04.2010
comment
Я думал об объектах - person gmhk; 30.04.2010
comment
Const-корректность - это то, что программист должен делать, не то, что они могут делать. Думаю, вы все поняли эту точку зрения. Просто хотел добавить пару центов, которые могли бы заинтересовать читателя: шаблоны проектирования, такие как immutable interface и immutable object, - это еще один способ (с которым можно справиться с приведением и отражением) имитировать константу в Java. Истинную константу можно сделать с помощью SealedObject, увы, это разрушает вариант использования нашего объекта. - person Martin Andersson; 20.02.2013
comment
Следует отметить, что результат вашей программы не определен. const_cast не используется для изменения переменных const, он предназначен для передачи переменных const в API, которые не являются правильными, но также не изменяют значение. Я думаю, что привычка думать, что что-то const не изменится, является хорошей, потому что, если они действительно меняются, это означает, что ваша программа содержит хаки, которые могут сломаться в любое время в зависимости от используемого компилятора. - person Cygon; 10.02.2015
comment
@Cygon в этом примере показывает, что вы можете использовать хакерский прием для создания неконстантного псевдонима. Но не все неконстантные псевдонимы являются взломами, например, передача c и c+1 в strncpy нарушит любое предположение в strncpy о том, что источник не изменится. - person Pete Kirkham; 10.02.2015
comment
@PeteKirkham Точно, и из-за этого передача перекрывающейся памяти в strncpy() тоже является взломом - она ​​попадает на неопределенную территорию: поведение strncpy не определено, если строки перекрываются (библиотека GNU C, аналогичные предупреждения в любой другой библиотеке C) . Только memmove() является исключением и требует особого подхода в реализации библиотеки для защиты от алиасинга. - person Cygon; 11.02.2015
comment
Изменение значения, рожденного константой, является неопределенным поведением. Возможно, ваш диск уже отформатирован. - person Zhe Yang; 20.05.2015
comment
@ZheYang, это иллюстрация. Более реалистичные проблемы обычно возникают, когда у вас есть один поток, изменяющий объект, который был передан другому как константная ссылка, и этот поток предполагает, что он не изменится, но это будет означать гораздо более длинный демонстрационный код. - person Pete Kirkham; 20.05.2015
comment
@anon совершенно неправильно утверждать, что const работает одинаково для объектов и для основных целочисленных типов. Это просто неправда. См. обсуждение в этом SO вопрос например. - person einpoklum; 12.10.2015
comment
Утверждение, что это outputs 42 then 7 неверно; поведение не определено. Ключ в том, что x был объявлен const (поэтому, например, он мог быть помещен в постоянную память). В этом примере компилятор может полностью проигнорировать присвоение и дважды напечатать 42. Если x был объявлен без const и был передан как константная ссылка на другую функцию, const_cast будет допустимым. - person SJL; 02.05.2017

Это немного старый вопрос, но я подумал, что все равно внесу свои 2 цента, так как эта ветка возникла сегодня в разговоре.

Это не совсем ответ на вопрос, почему нет const?, но как сделать ваши классы неизменяемыми. (К сожалению, у меня еще недостаточно репутации, чтобы оставлять комментарии к принятому ответу)

Чтобы гарантировать неизменность объекта, нужно более тщательно проектировать классы, чтобы они оставались неизменяемыми. Это требует немного большей осторожности, чем изменяемый класс.

Это восходит к Effective Java правилу 15 Джоша Блоха - Минимизируйте изменчивость. Если вы не читали книгу, возьмите копию и перечитайте ее несколько раз, я гарантирую, что она улучшит вашу образную "java-игру".

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

Чтобы процитировать книгу напрямую:

Неизменяемый класс - это просто класс, экземпляры которого нельзя изменить. Вся информация, содержащаяся в каждом экземпляре, предоставляется при его создании и фиксируется на время существования объекта. Библиотеки платформы Java содержат множество неизменяемых классов, включая String, упакованные примитивные классы, а также BigInteger и BigDecimal. Для этого есть много веских причин: неизменяемые классы легче разрабатывать, реализовывать и использовать, чем изменяемые классы. Они менее подвержены ошибкам и более безопасны.

Затем Блох описывает, как сделать ваши классы неизменными, следуя 5 простым правилам:

  1. Не предоставляйте никаких методов, которые изменяют состояние объекта (т. Е. Сеттеры, также известные как мутаторы).
  2. Убедитесь, что класс не может быть расширен (это означает объявление самого класса как final).
  3. Сделайте все поля final.
  4. Сделайте все поля private.
  5. Обеспечьте монопольный доступ ко всем изменяемым компонентам. (делая защитные копии объектов)

Для получения дополнительной информации настоятельно рекомендую взять книгу.

person grego    schedule 07.06.2016
comment
const в C ++ НАМНОГО гибче, чем полномасштабная неизменяемость. В некотором смысле «const» можно рассматривать как «неизменяемую в данном конкретном контексте». Пример: у меня есть класс, который не является неизменяемым, НО я хочу убедиться, что он не изменяется через определенные общедоступные API. Создание интерфейса (и возвращение его для этого общедоступного API), как предлагает Gunslinger47, дает то же самое в Java, но, черт возьми, это уродливо (и поэтому - оно игнорируется большинством разработчиков Java, что приводит к значительному ненужному беспорядку). . - person No-Bugs Hare; 26.10.2017

Семантика C ++ const сильно отличается от Java final. Если бы дизайнеры использовали const, это было бы излишне запутанным.

Тот факт, что const - зарезервированное слово, предполагает, что у дизайнеров были идеи по реализации const, но с тех пор они отказались от этого; см. эту закрытую ошибку. В число указанных причин входит то, что добавление поддержки стиля C ++ const вызовет проблемы совместимости.

person Stephen C    schedule 29.04.2010

В Java есть способ создавать "константные" переменные, но только для определенных классов. Просто определите класс с конечными свойствами и создайте подклассы. Затем используйте базовый класс, в котором вы хотели бы использовать «const». Точно так же, если вам нужно использовать «константные» методы, добавьте их в базовый класс. Компилятор не позволит вам изменить то, что он считает последними методами базового класса, но он будет читать и вызывать методы подкласса.

person user1122069    schedule 07.03.2016
comment
Не могли бы вы привести пример этого? - person NO_NAME; 31.01.2017
comment
класс MYString реализует GetString {private final String aaaa; общедоступная строка getString (); } class MutableString реализует GetString {private String aaaa2; общедоступная строка getString (); общедоступная строка setString ()} - person user1122069; 03.02.2017

Вы можете использовать static final, чтобы создать что-то, что работает аналогично Const, я использовал это в прошлом.

protected static final int cOTHER = 0;
protected static final int cRPM = 1;
protected static final int cSPEED = 2;
protected static final int cTPS = 3;
protected int DataItemEnum = 0;

public static final int INVALID_PIN = -1;
public static final int LED_PIN = 0;
person hamish    schedule 13.04.2013
comment
Проголосовали против оптимизации на основе слухов, потому что до меня доходили слухи, что это неэффективная стратегия. - person afarley; 02.05.2019
comment
Я удалил слух из ответа. вы все равно можете использовать static final int для создания кода в стиле констант. - person hamish; 01.07.2019
comment
Хорошо, я снял свой голос против. Возможно, некоторые другие отрицательные голоса относятся к оператору switch (какое отношение он имеет к остальной части вашего примера?) - person afarley; 02.07.2019
comment
в операторе switch я использовал cRPM, как если бы он был константой. Совершенно верно, учитывая вышесказанное. так что да, я снял переключатель. - person hamish; 02.07.2019

Было бы два способа определения констант - const и static final с точно такой же семантикой. Кроме того, static final описывает поведение лучше, чем const

person Bozho    schedule 29.04.2010
comment
@Bozho, ты сказал, что поведение лучше, чем Конст, как оно? можешь ли ты поделиться каким-нибудь примером? - person gmhk; 30.04.2010
comment
ну, переменная static (не принадлежит конкретному экземпляру) и final - не может быть изменена. - person Bozho; 30.04.2010