Зависит от того, что вы подразумеваете под "примитивом"
«Примитив» в 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, и машина может понять, как это сделать.