Как мы получаем доступ к методам String, даже если мы не используем новое ключевое слово? [Дубликат]

df.iloc[df['columnX'].argmax()]

argmax() предоставит индекс, соответствующий максимальному значению для столбцаX. iloc можно использовать для получения строки DataFrame df для этого индекса.

89
задан Michael Myers 7 January 2010 в 18:50
поделиться

14 ответов

В дополнение к тому, что уже было сказано, строковые литералы [т.е. строки, подобные "abcd", но не похожие на new String("abcd")] в Java, интернированы - это означает, что каждый раз, когда вы ссылаетесь на «abcd», вы получаете ссылку на один экземпляр String, а не новый каждый раз. Таким образом, у вас будет:

String a = "abcd";
String b = "abcd";

a == b; //True

, но если у вас есть

String a = new String("abcd");
String b = new String("abcd");

, то возможно иметь

a == b; // False

(и в случае необходимости Напоминаем, всегда используем .equals() для сравнения строк, == тестов для физического равенства).

Interning Строковые литералы хороши, потому что они часто используются более одного раза. Например, рассмотрим (надуманный) код:

for (int i = 0; i < 10; i++) {
  System.out.println("Next iteration");
}

Если бы у нас не было интернирования строк, «Следующая итерация» нужно было бы создать 10 раз, тогда как теперь он будет создан только один раз .

117
ответ дан Jonathan Leffler 20 August 2018 в 14:43
поделиться
  • 1
    Используя String a = new String («abcd»), означает ли это, что две строки с похожим содержимым присутствуют в памяти. – changed 5 January 2010 в 22:54
  • 2
    Правильно - компилятор не обязательно проверяет, была ли такая строка уже интернирована (хотя вы, безусловно, могли бы написать тот, который сделал). – danben 5 January 2010 в 22:57
  • 3
    да, эта оптимизация возможна, потому что строки неизменяемы и поэтому могут быть разделены без проблем. общий "asdf" обработка - это реализация шаблона дизайна «Веселый». – manuel aldana 6 January 2010 в 03:51
  • 4
    Никто не сказал, что это невозможно, только чтобы это не было гарантировано. Был ли это ваш downvote? – danben 6 January 2010 в 04:37
  • 5
    Что вы подразумеваете под «== тесты для равенства объектов»? Это не похоже на меня, но, возможно, вы имели в виду нечто иное, чем это означает. – Dawood ibn Kareem 30 November 2014 в 11:10
String a = "abc"; // 1 Object: "abc" added to pool

String b = "abc"; // 0 Object: because it is already in the pool

String c = new String("abc"); // 1 Object

String d = new String("def"); // 1 Object + "def" is added to the Pool

String e = d.intern(); // (e==d) is "false" because e refers to the String in pool

String f = e.intern(); // (f==e) is "true" 

//Total Objects: 4 ("abc", c, d, "def").

Надеюсь, что это несколько сомнений. :)

14
ответ дан Crocode 20 August 2018 в 14:43
поделиться
  • 1
    Строка d = новая строка («def»); // 1 Объект + "def" добавляется в пул - & gt; здесь "def" будет добавлен в пул, только если он еще не появился – southerton 25 June 2015 в 10:51
  • 2
    @southerton Бессмысленно. Он уже находится в бассейне. Он был размещен там компилятором. – user207421 7 February 2016 в 10:35
  • 3
    Наконец, что-то ясное и информативное! – Satyam 28 December 2016 в 17:55
  • 4
    @EJP почему (e == d) здесь ложь? они оба относятся к одному и тому же объекту "def" в бассейне? – Raja 16 July 2018 в 03:47

Строки являются «специальными» объектами в Java. Разработчики Java мудро решили, что Strings используются так часто, что им нужен собственный синтаксис, а также стратегия кэширования. Когда вы объявляете строку, говоря:

String myString = "something";

myString является ссылкой на объект String со значением «something». Если вы позже объявите:

String myOtherString = "something";

Java достаточно умен, чтобы понять, что myString и myOtherString одинаковы и будут хранить их в глобальной таблице String в качестве одного и того же объекта. Он полагается на то, что вы не можете изменять Strings для этого. Это уменьшает объем требуемой памяти и ускоряет сравнение.

Если вместо этого вы напишете

String myOtherString = new String("something");

Java создаст для вас совершенно новый объект, отличный от myString объект.

29
ответ дан Jamie McCrindle 20 August 2018 в 14:43
поделиться

Это ярлык. Это было не так, но Java изменил его.

Этот FAQ говорит об этом кратко. Об этом также говорит руководство по спецификации Java. Но я не могу найти его в Интернете.

6
ответ дан Malfist 20 August 2018 в 14:43
поделиться
  • 1
    Сломанная ссылка, и я не знаю никаких других доказательств того, что она когда-либо менялась. – user207421 7 February 2016 в 10:34
  • 2
    @EJP Он все еще находится в машине wayback , если это полезно. – Arjan 15 August 2016 в 02:54

Невозможно создать новую строку с

String s = new String("I'm a new String");

. Обычная нотация s = "new String"; - более или менее удобный ярлык - который следует использовать по соображениям производительности, за исключением тех редких случаев, где вам действительно нужны строки, которые подходят для уравнения

(string1.equals(string2)) && !(string1 == string2)

EDIT

В ответ на комментарий: это не предназначалось для консультирования, а просто для прямого ответа на что мы не используем ключевое слово 'new' для строк, что просто неверно. Надеюсь, что это редактирование (в том числе и выше) немного разъясняет это. BTW - есть пара хороших и гораздо лучших ответов на вышеупомянутый вопрос о SO.

0
ответ дан Andreas_D 20 August 2018 в 14:43
поделиться
  • 1
    -1 - Плохой совет. Вы НЕ должны «чувствовать себя свободно». использовать new String(...), ЕСЛИ ваше приложение НЕОБХОДИМО создать строку с отдельным идентификатором. – Stephen C 6 January 2010 в 00:49
  • 2
    Я знаю это. Отредактировал сообщение для разъяснения. – Andreas_D 6 January 2010 в 09:34

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

6
ответ дан Brian Agnew 20 August 2018 в 14:43
поделиться
  • 1
    + - фактически оператор, который преобразуется в вызов StringBuilder.append (..). – whiskeysierra 5 January 2010 в 23:37

В Java строки являются особым случаем со многими правилами, которые применяются только к строкам. Двойные кавычки заставляют компилятор создавать объект String. Поскольку объекты String неизменяемы, это позволяет компилятору ставить несколько строк и создавать более большой пул строк. Две одинаковые строковые константы всегда будут иметь одну и ту же ссылку на объект. Если вы не хотите, чтобы это было так, вы можете использовать новую строку String (""), и это создаст объект String во время выполнения. Метод intern () обычно был общим, чтобы вызвать динамически создаваемые строки для проверки в таблице поиска строк. После того, как строка в интернированном, ссылка на объект укажет на канонический экземпляр String.

    String a = "foo";
    String b = "foo";
    System.out.println(a == b); // true
    String c = new String(a);
    System.out.println(a == c); // false
    c = c.intern();
    System.out.println(a == c); // true

Когда загрузчик классов загружает класс, все String-константы добавляются в пул строк.

1
ответ дан brianegge 20 August 2018 в 14:43
поделиться

Нет необходимости в новой строке, поскольку литерал (символы в кавычках) уже является объектом String, созданным при загрузке класса хоста. Совершенно законно ссылаться на методы на буквальном и донном, основное различие - удобство, предоставляемое литералами. Было бы большой болью и тратой времени, если бы нам пришлось создать массив символов и заполнить его char символом char, и они будут создавать новую строку (char array).

0
ответ дан mP. 20 August 2018 в 14:43
поделиться

Поскольку String является неизменным классом в java.

Теперь почему это неизменное? Поскольку String является неизменным, поэтому он может быть разделен между несколькими потоками, и нам не нужно синхронизировать операцию String извне. Поскольку String также используется в режиме загрузки классов. Поэтому, если String изменен, тогда java.io.writer можно было бы изменить на abc.xyz.mywriter

0
ответ дан Mr37037 20 August 2018 в 14:43
поделиться

Вы все еще можете использовать new String("string"), но создавать новые строки без строковых литералов сложнее ... вам придется использовать массивы символов или байты :-) Строковые литералы имеют одно дополнительное свойство: все те же строковые литералы из любой класс указывает на тот же экземпляр строки (они интернированы).

0
ответ дан Peter Štibraný 20 August 2018 в 14:43
поделиться

Синтаксический сахар. Синтаксис

String s = new String("ABC");

все еще доступен.

0
ответ дан Seva Alekseyev 20 August 2018 в 14:43
поделиться
  • 1
    Это не совсем правильно. s = новая строка («ABC») не даст вам тех же результатов, что и s = «ABC». См. Комментарий данбена. – Steve B. 5 January 2010 в 22:41
  • 2
    Кроме того, по иронии судьбы, он сначала создаст экземпляр String, представляющий «ABC». inline - и затем передать это как аргумент вызову конструктора, который создаст возвращаемый String с одинаковым значением. – Andrzej Doyle 6 January 2010 в 09:39
  • 3
    Допустимым примером использования этого конструктора является String small = new String(huge.substring(int, int));, что позволяет вам перерабатывать большую базовую char[] из исходной строки huge. – Pascal Thivent 26 January 2010 в 06:39
  • 4
    @PascalThivent да, но не больше с Java 8. Он больше не разделяет массивы (в рамках подготовки к другим оптимизациям, таким как автоматическая дедупликация строк с G1 или предстоящее сжатие строк). – eckes 21 August 2015 в 18:51
  • 5
    @AndrzejDoyle Неправильно. Компилятор создает объект для литерала. – user207421 7 February 2016 в 10:35

Литеральный пул содержит любые строки, которые были созданы без использования ключевого слова new.

Существует разница: строка без новой ссылки сохраняется в строковом литеральном пуле, а String с новым говорит, что они в памяти кучи.

Строка с новыми находится в другом месте в памяти, как и любой другой объект.

0
ответ дан Stephan 20 August 2018 в 14:43
поделиться
TString obj1 = new TString("Jan Peter");                
TString obj2 = new TString("Jan Peter");                    

if (obj1.Name == obj2.Name)                 
    System.out.println("True");
else                
    System.out.println("False");

Выход:

True

Я создал два отдельных объекта, у обоих есть поле (ref) 'Name'. Так что даже в этом случае «Ян Питер» является общим, если я понимаю, как работают java.

0
ответ дан Tom 20 August 2018 в 14:43
поделиться
0
ответ дан Joby Wilson Mathews 31 October 2018 в 11:07
поделиться
Другие вопросы по тегам:

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