Почему Java имеет “Строковый” тип и не “строку”?

Класс обертки очень хорошо, и их цель также хорошо понята. Но почему мы опускаем тип примитива?

16
задан Robert Fraser 21 January 2010 в 11:52
поделиться

6 ответов

Это зависит от того, что вы подразумеваете под «примитивом»

«Примитивный» в Java обычно означает «тип значения». Однако в C # есть ключевое слово string , которое действует точно так же, как String в Java, просто оно выделяется редактором по-другому. Это псевдонимы для классов System.String или java.lang.String . Строка не является типом значения ни на одном из языков, поэтому в этом смысле она не является примитивом.

Если под «примитивом» вы подразумеваете встроенный в язык, то String является примитивом. Он просто использует заглавную букву. Строковые литералы (заключенные в кавычки) автоматически преобразуются в систему .Строка и + используется для конкатенации. Таким образом, по этому токену они (и массивы) столь же примитивны, как целые, длинные и т. Д.

Во-первых, что такое String?

String не является оболочкой. Строка - это ссылочный тип , а примитивные типы - это типы значений . Это означает, что если у вас есть:

int x = 5;
int y = x;

В памяти x и y содержится «5». Но с:

String x = "a";
String y = x;

Память для x и y содержит указатель на символ «a» (и длину, смещение, указатель ClassInfo и монитор). Строки ведут себя как примитивы, потому что они неизменяемы, поэтому обычно это не проблема, однако, если вы, скажем, использовали отражение для изменения содержимого строки ( не делайте этого! ), оба x и y увидит изменение. Фактически, если у вас есть:

char[] x = "a".toCharArray();
char[] y = x;
x[0] = 'b';
System.out.println(y[0] == 'b'); // prints "true"

, поэтому не используйте просто char [] (если это не то поведение, которое вы хотите, или вы действительно пытаетесь уменьшить использование памяти).

Каждый объект является ссылочным типом - это означает все классы, которые вы пишете, каждый класс в структуре и даже массивы. Единственные вещи, которые являются типами значений, - это простые числовые типы (int, long, short, byte, float, double, char, bool и т. Д.)

Почему String не может быть изменен, как char []?

Там есть пара причин для этого, но в основном это сводится к деталям психологии и реализации:

  • Представьте себе хаос, который возник бы, если бы вы передали строку в другую функцию, и эта функция как-то ее изменила.Или что, если он где-то сохранил и изменил в будущем? Для большинства ссылочных типов вы принимаете это как часть типа, но разработчики Java решили, что, по крайней мере, для строк, они не хотят, чтобы пользователи беспокоились об этом.
  • Со строками нельзя обращаться атомарно, что означает, что многопоточность / синхронизация могут стать проблемой.
  • Строковые литералы (то, что вы помещаете в свой код в кавычки) могут быть неизменными на уровне компьютера 1 (из соображений безопасности). Это можно было обойти, скопировав их все в другую часть памяти при запуске программы или используя копирование при записи, но это медленно .

Почему у нас нет версии строки с типом значения?

В основном, это детали производительности и реализации, а также сложность наличия двух разных типов строк. Другие типы значений имеют фиксированный объем памяти. Int всегда 32 бита, long всегда 64 бита, bool всегда 1 бит и т. Д. 2 Среди прочего, это означает, что они могут храниться в стеке, чтобы все параметры функция находится в одном месте. Кроме того, создание гигантских копий струн повсюду убивает производительность.

См. Также: Почему в C # String является ссылочным типом, который ведет себя как тип значения? . Относится к .NET, но это также применимо к Java.

1 - В C / C ++ и других языках с встроенной компиляцией это верно, потому что они помещаются в сегмент кода процесса, который ОС обычно не дает вам редактировать.В Java это на самом деле , обычно неверно, поскольку JVM загружает файлы классов в кучу, так что вы можете редактировать там строку. Однако нет причин, по которым Java-программа не может быть скомпилирована изначально (есть инструменты, которые это делают), а некоторые архитектуры (особенно некоторые версии ARM) делают напрямую исполняют байт-код Java.

2 - На практике,некоторые из этих типов имеют другой размер на уровне машины. Бывший. bools хранятся в стеке как WORD-size (32 бита на x86, 64 бита на x64). В классах / массивах они могут трактоваться по-разному. Это все детали реализации, которые оставлены на усмотрение JVM - в спецификации указано, что bools истинны или ложны, и машина может понять, как это сделать.

41
ответ дан 30 November 2019 в 15:32
поделиться

Примитивный тип для строки Char [] .

Это верно для многих языков (C, Java, C #, C ++ и многое другое ...).

10
ответ дан 30 November 2019 в 15:32
поделиться

Строка - это своего рода особый случай. Все настоящие примитивные типы (INT, длинные и т. Д.) являются побыточными и реализованы непосредственно в JVM. Строка представляет собой ссылочный тип, и поэтому имел дело с любым другим классом (заглавная буква, пропускной справочник ...), кроме компилятора имеет специальные крючки для того, чтобы иметь дело с ним, как встроенный тип (+ для объединения строки, Например).

Как уже есть тип ссылочного типа, он не нужен класс обертки, как целое число, чтобы иметь возможность использовать его как класс (в коллекциях, например)

0
ответ дан 30 November 2019 в 15:32
поделиться

Строки могут быть произвольной длины. Отцы Java не хотели иметь примитивный тип, для которого они не могли назначить размер бетонного памяти. Это одна из главных причин строки не является примитивной в Java.

3
ответ дан 30 November 2019 в 15:32
поделиться

Примитивный?

Если Java нет примитивных строк. Примитивы int, float, двойные, логические и т. Д. ... и char.

Так что для использования строк они использовали объект. Вы показываете, что он живет в куче, у вас есть ссылка на него и т. Д.

Как они это реализовали? Сохранение значения, которое он представляет в массиве Char.

Незнаваемость

, но они обеспечили представимость. Когда у вас есть ссылка на строковый объект, вы , знаете , вы можете свободно передавать его на другие объекты, зная стоимость, указанное в том, что эта ссылка не изменится . Все методы, которые изменяют строки, возвращает другой экземпляр строки, поэтому он не изменяет значение, представленное другими ссылками на строку.

Может ли это быть другим способом (как в .NET)

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

Но они не ...

0
ответ дан 30 November 2019 в 15:32
поделиться

Таково нормальное поведение. Функция delete () не удаляет индекс, а только его содержимое. Таким образом, у вас все еще есть 2 элементов в массиве, но при индексном 0 у вас будет undefined .

-121--3815237-

РИДМИ , предложенный Chris J , может работать при условии, что он настроен с помощью пользовательского драйвера слияния, определенного в .gitattribute .
Таким образом, локальная версия README всегда сохраняется во время слияния.

«Описание» для ветвей также известно как «комментарий», связанный с этими метаданными, и оно не поддерживается.

По крайней мере, с помощью файла РИДМИ можно для любой ветви сделать:

$ git show myBranch:README

Если ваше РИДМИ находится в корневом каталоге РЕПО, он будет работать по любому пути, так как путь, используемый git show , является абсолютным из верхнего каталога указанного РЕПО.

-121--567343-

Последовательность является массивом символов. Поскольку это массив, он не может быть примитивом!: -)

-1
ответ дан 30 November 2019 в 15:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: