Подтвердить что ты не робот

В Java, почему мы можем использовать класс String, как если бы он был примитивным?

В Java мы обычно делаем:

Class myObject = new Class();

потому что ключевое слово new возвращает адрес.

Но почему мы можем это сделать?:

String myString = "Hello";

как будто String был примитивным?

Я спросил об этом своего учителя, и он ответил, что это потому, что то, что в кавычках эквивалентно адресу, но он не уверен. Можешь подтвердить?

Является ли "Hello" хранимым в переменной экземпляра класса String?

4b9b3361

Ответ 1

... как если бы String были примитивными?

Как Джон указывает в комментарии, "имеет буквальную форму" != "является примитивным типом".:-) Строки имеют буквальную форму на Java, потому что спецификация определяет один для них. String все еще является типом объекта.

Некоторые языки имеют другие типы объектов, которые также имеют буквенные формы (например, у JavaScript есть литералы для регулярных выражений, массивов и объектов без массива [его буквальная форма для строк фактически определяет то, что она называет строковым примитивным, чем строковый объект — JavaScript имеет как примитивные, так и объектные версии строк]). Я думаю, что строки являются единственными в Java (кроме null, который является литералом для "no object" ), хотя, конечно, есть инициализаторы массива, которые похожи, но не совсем такие же, как литералы.

Ответ 2

Тот факт, что вы можете использовать выражение литерал, не означает, что выражение приводит к примитивному типу! Это просто заблуждение на вашем конце.

Вы видите:

 Integer[] numbers = { 1, 2, 3 };

также является литералом (ну, "почти", поскольку вы можете использовать его только для таких операторов массива init); но это не примитивный тип!

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

В этом смысле: введение строковых литералов можно рассматривать как уникальный пункт продажи, чтобы отличать Java от его конкуренции!

Ответ 3

Другие ответы довольно хорошие. Некоторые конкретные моменты:

Я спросил об этом своего учителя, и он ответил, что это потому, что то, что в кавычках эквивалентно адресу, но он не уверен. Можете ли вы подтвердить?

Да. Он прав. Как указывали другие, строковый литерал, то есть действительная последовательность символов Юникода, заключенная внутри пары "s", распознается спецификацией языка Java. Когда Java-компилятор (программа javac) встречает такой литерал (например, "Hello") в исходном файле Java, он берет его буквально и помещает его в определенный раздел внутри скомпилированного файла . Этот раздел называется который затем помещает в файл класса, где хранится скомпилированный код для вашей инициализации. Например, тело метода main в следующем исходном коде Java:

public class StringAsPrimitive {
    public static void main(String[] args) {
        String s = "Hello";
    }
}

скомпилируется в:

     0: ldc           #2                  // String Hello
     2: astore_1
     3: return

(Здесь нет никакой магии. Просто скомпилируйте свой код с помощью программы javac и просмотрите файл класса с помощью программы javap. Вы даже можете увидеть содержимое файла .class с помощью шестнадцатеричного зрителя, и вы увидите Строка Hello буквально).

Этот код затем интерпретируется JVM, когда вы запрашиваете программу java для запуска этого файла класса.

Инструкция ldc для JVM документирована здесь. Это то, что делает JVM, когда он интерпретирует #2, который является ссылкой на фактическое место, где буквальная строка "Hello" хранится в памяти компьютера (ОЗУ):

В противном случае, если запись пула постоянной времени выполнения является ссылкой на экземпляр класса String, представляющий строковый литерал (§5.1), тогда a ссылка на этот экземпляр, значение, помещается в стек операнда.

Итак, то, что сказал ваш учитель, оказывается правильным, хотя мы не говорим об этом совершенно так. В Java существует два типа типов: примитивный и справочный. Таким образом, было бы более уместным сказать, что значение строкового литерала является ссылкой (а не адресом).

Является ли "Hello" хранимым в переменной экземпляра класса String?

Нет. Переменная String, инициализированная строковым литералом, может быть любой, переменной static или class, переменной экземпляра или локальной переменной (мой код выше). Он хранится в файле класса: StringAsPrimitive.class, а затем он доступен JVM в определенной ячейке памяти. Это происходит, когда JVM загружает класс.

Ответ 4

Все литералы не являются примитивами.

От JLS 3.10

3,10. Литералов

Литерал - это представление исходного кода значения примитива тип (§4.2), тип String (§ 4.3.3) или нулевой тип (§ 4.1).

буквенный:

IntegerLiteral

FloatingPointLiteral

БулевскийЛитерал

CharacterLiteral

СтроковойЛитерал

NullLiteral

Итак, String литералы - это не примитивы, а объекты.

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

Строковые литералы (String myString = "Hello"), скорее всего, были введены языком, чтобы облегчить объявление String, которое является типом, распространенным как примитивные типы, такие как int или boolean. Представьте себе конкатенацию String, например:

new String("hello ") + new String (nameInput) + new String (" and welcome!");

Это явно более подробный, менее читаемый и, следовательно, более подверженный ошибкам, чем:

 "hello " + nameInput +" and welcome!";