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


142

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

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

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


2
Там естьconst ключевое слово, но не основная функция. Соответственно исправлены заголовок и теги.
Маркиз Лорн,

Ответы:


143

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

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

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


10
Однако Java finalпохожа.
Reinierpost

64
Нет, это не так. finalНапример, метод работы полностью отличается от constметодов C ++ .
dom0

7
@reinierpost finalКлючевое слово свойств или переменных просто гарантирует, что свойство или переменная назначается только один раз . Можно еще изменить состояние этого объекта, например, вызвав какой-нибудь метод с побочными эффектами. finalнесколько похоже на выделение стека в C ++ с точки зрения ссылки на объект, а не на указатель, но это все. Это, конечно, в дополнение к тому, что уже сказал dom0.
Тим

9
finalв Java, похоже, работает как C ++ constдля типов значений, но больше как неконстантный C ++ T&для ссылочных типов
Марк К. Коуэн,

1
final - ключевое слово шизофреника. Хотя он предотвращает переназначение, он также используется для закрытия переменных. Я мог бы предотвратить переназначение, но не раскрывать эти переменные, но нет способа сделать это. На мой взгляд, это довольно плохо продуманная языковая функция.
Дэвид Брэдли

82

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

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

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

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

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

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

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


2
+1 только за вторую часть вашего ответа. Многие ключевые слова имеют нетривиальную семантику. Является ли volatileтак просто понять? Или final? Мех.
einpoklum

OTOH, Java была разработана таким образом, чтобы использовать как можно меньше этих нетривиальных функций. И я не говорю, что они достигли этой цели (или что Java не отошла от этой цели). Но исключение его по этой причине, возможно, все же имело смысл. То, что есть другие сложные вещи, - это еще одна причина не вводить больше (иначе вы в конечном итоге перейдете на язык D).
Маартен Бодевес,

7

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

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

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

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

например:

#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просто означает, что ваш код не может изменить его без приведения, а не то, что значение является постоянным.


3
const int x = 42; - x - константа

2
@Neil Если у вас есть один объект или переменная с псевдонимом константных и неконстантных указателей, то значение псевдонима const может быть изменено с помощью псевдонима неконстант. Следовательно, constэто не означает, что значение является постоянным. Это означает, что клиент значения не может изменять его. В вашем примере нет псевдонима, поэтому все пользователи находятся под одним и тем же ограничением. В общем случае это не так. constвлияет на клиентов, а не на ценность - он говорит, что вы не можете это изменить, а не то, что это не изменится.
Пит Киркхэм

1
Постоянная корректность - это то, что должен делать программист , а не то, что он может . Думаю, вы все поняли эту точку зрения. Просто хотел добавить пару центов, которые могли бы заинтересовать читателя: шаблоны проектирования, такие как immutable interfaceи, immutable object- это еще один способ (с которым можно справиться с приведением и отражением) имитировать константу в Java. "Истинная" константа может быть выполнена с помощью SealedObject , но , увы, это разрушает вариант использования нашего объекта.
Мартин Андерссон,

6
Следует отметить, что результат вашей программы не определен. const_cast не используется для изменения переменных const, он предназначен для передачи переменных const в API, которые не являются правильными, но также не изменяют значение. Я думаю, что привычка думать, что что-то const не изменится, является хорошей, потому что если они действительно меняются, это означает, что ваша программа содержит хаки, которые могут сломаться в любое время в зависимости от используемого компилятора.
Cygon

1
Изменение рожденного в постоянное значение является неопределенным поведением. Возможно, ваш диск уже отформатирован.
Чжэ Ян

6

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

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

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

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

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

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

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

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

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

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


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

3

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

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


-1

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


Не могли бы вы привести пример этого?
NO_NAME

класс MYString реализует GetString {закрытая конечная строка aaaa; общедоступная строка getString (); } class MutableString реализует GetString {private String aaaa2; общедоступная строка getString (); public String setString ()}
user1122069 03

-1

Вы можете использовать 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;

Проголосовал за оптимизацию на основе слухов, потому что до меня доходили слухи, что это неэффективная стратегия.
afarley

Я удалил слух из ответа. вы все равно можете использовать static final int для создания кода в стиле const.
hamish 01

Хорошо, я снял свой голос против. Может быть, некоторые из других отрицательных голосов относятся к оператору switch (какое оно имеет отношение к остальной части вашего примера?)
afarley

в операторе switch я использовал cRPM, как будто это константа. совершенно верно, учитывая вышесказанное. так что да, я снял переключатель.
hamish 02

-2

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


@Bozho, ты сказал, что поведение лучше, чем у Конст, как оно?
Можете

ну, переменная static(не принадлежит конкретному экземпляру) и final- не может быть изменена.
Божо
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.