Почему String - единственный класс, для которого в Java существуют литералы?
Вопрос
Почему это java.lang.String
единственный класс, для которого существуют два способа создания:
1) Обычным способом с "new
" ключевое слово.
String s = new String("abc");
2) С помощью String
литерал (который доступен только с String
класс)
String s = "abc";
Так почему же они существуют String
литералы и никаких литералов для каких-либо других классов??
Решение
Строка, будучи обычным классом, представляет собой один из основных элементов программирования (остальные - числа и логические значения). Поэтому Java считала объекты String полупримитивными переменными с первого дня и позволяла это.
Позже, когда автобокс стал частью стандартного компилятора, вы также можете создавать числовые объекты-оболочки таким образом, т.е.
Integer i = 123;
как упоминает Том Хотин-таклайн в комментариях к вопросу.
Другие советы
Короткий ответ, потому что дизайнеры языка чувствовали это так.
Я думаю, что String - такой распространенный класс, что они сделали исключение. Я уверен, что есть и другие подобные исключения (см. Комментарий Тома Хоутинса)
Оставляя в стороне автобокс (который не учитывает IMO - литералы относятся к примитивным типам, а не к классам; существует просто неявное преобразование в класс-оболочку), конструктор String (String)
на самом деле полезно. Для этого требуется копия символьных данных, что означает, что если строка original мала, но с большой подложкой char []
, новая строка не зависит от нее. р>
Это может быть важно, например, если вы читаете короткие строки из файла.
Что касается того, почему существуют строковые литералы: потому что они полезны. Что бы вы имели вместо этого? Хотите ли вы заставить разработчиков использовать:
String x = new String(new char[] { 'h', 'e', 'l', 'l', 'o' });
и в то же время не проходить стажировку?
Для какого другого класса вы бы хотели получить литерал? Возможно, были бы полезны литералы для карт и списков - я не могу вспомнить, появятся они в Java 7 или нет. Вы можете думать об инициализаторах массива как о «немного похожем на литерал». в том, что это сокращение для инициализации объекта.
Я полагаю, поскольку String является таким фундаментальным типом данных, они рассматривают его на том же уровне, что и примитивы.
Кстати,
new String("abc");
фактически создает 2 Строки:
- интернированный, ссылку на который вы теряете
- новый экземпляр с тем же содержимым
Лично я никогда не видел необходимости использовать конструктор String .
Типы объектов, которые имеют литералы: Строки , null и литералы класса . р>
Также можно использовать инициализаторы для массивов и примитивные литералы также можно использовать для создания объектов, если они используются в качестве инициализаторов, которые соответствуют «двум способам создания». в простом синтаксисе, не будучи истинными литералами (они могут использоваться только для инициализации значения, а не во всех местах, где может возникнуть выражение объекта).
Если вы используете другие методы, такие как сериализация и рефлексия, вы можете нарушить "два способа создания". тоже.
Предполагается, что Java 7 предоставит возможность создавать начальные коллекции с помощью литералов, очень похожих на литералы массива:
Последнее, что я проверял:
Integer wInt = 1;
Работает просто отлично.
Последняя форма создания также включает в себя интернирование строк. То есть, если у вас есть код:
String s = "abc";
String t = "abc";
компилятор оптимизирует это, и вы получите две ссылки на один и тот же объект String. (s == t будет правдой).
Строковое интернирование работает и для строковых выражений.
Конечно, есть также литералы для всех примитивных числовых типов, а также логические значения true и false, а также символы. Полагаю, вы могли бы ответить, что в своем вопросе вы технически сказали «никаких литералов для любых других классов ». Хорошо. Я думаю, что кто-то указал, что "ноль" это буквальный объект, так что ваше утверждение технически неточно, но я думаю, что это единственный другой пример.
Но тогда возникает следующий очевидный вопрос: для каких других классов вы хотели бы иметь литералы? Если бы вы разрабатывали язык, как бы выглядел литерал BufferedReader? Или литерал ResultSet? Или JCheckBox?
Теоретически можно сказать, что, например, " Файловый литерал " это имя файла, заключенное в некоторый специальный разделитель, например " $ / home / bob / myfile.txt $ " ;. Но тогда кто-то может сказать: как насчет JButton, мы не можем сделать для этого литерал, например, с помощью текста кнопки и ActionListener, который она запускает, и соответствующих разделителей, таких как "% Submit, SubmitListener% " ;. А что касается Sockets, мы не можем поместить имя хоста в какой-то специальный разделитель и т. Д. Я думаю, что совершенно очевидно, что у нас быстро закончатся знаки препинания для использования в качестве разделителей. Поэтому нам пришлось бы написать какой-то текст, чтобы определить, о каком классе мы говорим, например, сказать File (" /home/bob/myfile.txt") или Socket (" www.example.com " , 631). Но это очень похоже на конструктор, и мы вернемся к тому, что на самом деле сделали авторы Java.
Количество " вещей " это может быть выражено исключительно природой значения (например, все цифры составляют числовой литерал) или с помощью знаков препинания довольно ограничено числом знаков препинания, которые могут быть разумно помещены на клавиатуре. И хотите ли вы клавиатуру с 600 специальными значками для всего того, о чем вы могли бы поговорить? Слова намного проще и гибче.
Строка используется так часто, и альтернативы были бы настолько неуклюжими, что имело смысл сделать это особым случаем.
Строковые литералы - это удобное сокращение с хорошо установленным приоритетом (в Си) и синтаксисом. Если Java-дизайнеры хотели заманить программистов на C ++, там должны быть строковые литералы. К счастью, обработка строк в Java намного удобнее, чем в C ++.
Ни один другой стандартный объект не имел де-факто синтаксиса - как бы вы написали литерал карты? Р>