Почему Java имеет тип "String", а не "string"? - PullRequest
16 голосов
/ 21 января 2010

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

Ответы [ 6 ]

41 голосов
/ 21 января 2010

Зависит от того, что вы подразумеваете под "примитивом"

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

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

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

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

int x = 5;
int y = x;

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

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

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

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

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

Каждый Object является ссылочным типом - это означает, что все классы, которые вы пишете, каждый класс в каркасе и даже массивы. Единственными вещами, которые являются типами значений, являются простые числовые типы (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) do напрямую выполняют байт-код Java.

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

10 голосов
/ 21 января 2010

Тип примитива для String равен char[].

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

3 голосов
/ 21 января 2010

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

0 голосов
/ 21 января 2010

Примитивный

Если в Java нет примитива для строк. Примитивами являются int, float, double, boolean и т. Д. ... и char.

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

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

Inmutability

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

Может ли быть иначе (как в .Net)

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

Но они не ...

0 голосов
/ 21 января 2010

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

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

0 голосов
/ 21 января 2010

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

...