Почему String единственный класс, для которого литералы существуют в Java? - PullRequest
2 голосов
/ 10 сентября 2009

Почему java.lang.String единственный класс, для которого существуют два способа создания:

1) Обычным способом с ключевым словом "new".

String s = new String("abc");

2) С литералом String (который доступен только для класса String)

String s = "abc";

Так почему существуют литералы String и никаких литералов для каких-либо других классов ??

Ответы [ 10 ]

10 голосов
/ 10 сентября 2009

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

Полагаю, String - такой распространенный класс, что они сделали исключение. Я уверен, что есть еще несколько подобных исключений (см. Комментарий Тома Хоутинса)

5 голосов
/ 10 сентября 2009

Оставляя в стороне автобокс (который не учитывает IMO - литералы относятся к примитивным типам, а не к классам; существует просто неявное преобразование в класс-оболочку), конструктор String(String) действительно полезен. Он берет копию символьных данных, что означает, что если строка оригинал мала, но имеет большой отступ char[], новая строка не зависит от нее.

Это может быть важно, например, если вы читаете короткие строки из файла.

Что касается того, почему существуют строковые литералы: потому что они полезны. Что бы вы имели вместо этого? Хотите ли вы заставить разработчиков использовать:

String x = new String(new char[] { 'h', 'e', 'l', 'l', 'o' });

и при этом не пройти стажировку?

Для какого другого класса вы бы хотели получить литерал? Возможно, были бы полезны литералы для карт и списков - я не могу вспомнить, появятся они в Java 7 или нет. Вы можете думать об инициализаторах массива как о «немного похожем на литерал» в том смысле, что это сокращение для инициализации объекта.

3 голосов
/ 10 сентября 2009

Я полагаю, потому что String является таким фундаментальным типом данных, что они считают его на том же уровне, что и примитивы.

Btw

new String("abc");

фактически создает 2 строки:

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

Лично мне никогда не приходилось использовать конструктор String.

2 голосов
/ 10 сентября 2009

Строка, будучи обычным классом, представляет собой один из базовых элементов программирования (остальные - числа и логические значения). Поэтому Java считала объекты String полупримитивными переменными с первого дня и позволяла это.

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

Integer i = 123;

как упоминает Том Хотин-таклайн в комментариях к вопросу.

1 голос
/ 10 сентября 2009

Java 7 намечена для предоставления возможности начальных коллекций с помощью литералов, очень похожих на литералы массива:

1 голос
/ 10 сентября 2009

Типы объектов, которые имеют литералы: Строки , null и литералы класса .

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

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

0 голосов
/ 10 сентября 2009

Строковые литералы - это удобное сокращение с хорошо установленным приоритетом (в Си) и синтаксисом. Если Java-дизайнеры хотели заманить программистов на C ++, там должны быть строковые литералы. К счастью, обработка строк в Java намного удобнее, чем в C ++.

Ни один другой стандартный объект не имел де-факто синтаксиса - как бы вы написали литерал карты?

0 голосов
/ 10 сентября 2009

Конечно, есть также литералы для всех примитивных числовых типов, а также логические значения true и false, а также символы. Полагаю, вы могли бы ответить, что в своем вопросе вы технически сказали «нет литералов для любых других классов ». Хорошо. Я думаю, что кто-то указал, что «ноль» - это буквальный объект, поэтому ваше утверждение является технически неточным, но я думаю, что это единственный другой пример.

Но тогда следующий очевидный вопрос: для каких других классов вы хотели бы иметь литералы? Если бы вы разрабатывали язык, как бы выглядел литерал BufferedReader? Или литерал ResultSet? Или JCheckBox?

Теоретически можно сказать, что, например, «File literal» - это имя файла, заключенное в некоторый специальный разделитель, такой как «$ / home / bob / myfile.txt $». Но тогда кто-то может сказать: как насчет JButton, мы не могли бы сделать для этого литерал, например, с помощью текста кнопки и ActionListener, который она запускает, и соответствующих разделителей, таких как «% Submit, SubmitListener%». А что касается Sockets, мы не можем поместить имя хоста в какой-то специальный разделитель и т. Д. Я думаю, что совершенно очевидно, что у нас быстро закончатся знаки препинания для использования в качестве разделителей. Поэтому нам пришлось бы написать какой-то текст, чтобы определить, о каком классе мы говорим, например, сказать File ("/ home / bob / myfile.txt") или Socket ("www.example.com", 631 ). Но это очень похоже на конструктор, и мы вернемся к тому, что на самом деле сделали авторы Java.

Количество «вещей», которые могут быть выражены исключительно природой значения (например, все цифры составляют числовой литерал) или с помощью знаков препинания, довольно ограничено количеством знаков препинания, которые могут быть разумно помещены на клавиатуре. И хотите ли вы клавиатуру с 600 специальными значками для всего того, о чем вы могли бы поговорить? Слова намного проще и гибче.

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

0 голосов
/ 10 сентября 2009

Последняя форма создания также включает в себя интернирование строк.То есть, если у вас есть код:

String s = "abc";
String t = "abc";

, компилятор оптимизирует это, и вы получите две ссылки на один и тот же объект String.(s == t будет true).

Интернирование строк работает и для строковых выражений.

0 голосов
/ 10 сентября 2009

Последнее, что я проверял:

Integer wInt = 1;

Работает просто отлично.

...