Строка s = новая строка ( "xyz" ). Сколько объектов было сделано после выполнения этой строки кода?
Общепринятый ответ на этот вопрос интервью состоит в том, что код создает два объекта. Но я так не думаю; Я написал код для подтверждения.
public class StringTest {
public static void main(String[] args) {
String s1 = "a";
String s2 = "a";
String s3 = new String("a");
System.out.println("s1: "+s1.hashCode());
System.out.println("s2: "+s2.hashCode());
System.out.println("s3: "+s3.hashCode());
}
}
Вывод:
![Application output]()
Означает ли это, что был создан только один объект?
Подтвердите: мой вопрос: сколько объектов было создано с помощью следующего кода:
String s = new String("xyz")
Вместо кода StringTest
.
Вдохновленный @Don Branson, я отлаживал приведенный ниже код:
public class test {
public static void main(String[] args) {
String s = new String("abc");
}
}
И результат:
![Enter image description here]()
Идентификатор s равен 84, а идентификатор "abc" равен 82. Что именно это означает?
Ответы
Ответ 1
ОШИБКИ НИЖЕ ЗАВИСИМО ОТ JVM/JRE, КОТОРЫЕ ВЫ ИСПОЛЬЗУЕТЕ. ЭТО ЛУЧШЕ, ЧТОБЫ НЕ МОЖЕТ БЫТЬ ОБРАБОТАТЬ О ВЕЩИ, КАК ЭТО ВЕРОЯТНО. СМ. ЗАМЕЧАНИЯ РАЗДЕЛА ДЛЯ ЛЮБЫХ ИСПРАВЛЕНИЙ/КОНЦЕРН.
Во-первых, этот вопрос действительно спрашивает об этом здесь:
Является ли String Literal Pool набор ссылок на объект String или набор объектов
Итак, это руководство для всех по этому вопросу.
...
С учетом этой строки кода: String s = new String("xyz")
Есть два способа взглянуть на это:
(1) Что происходит, когда выполняется строка кода - буквальный момент, который он запускает в программе?
(2) Каков чистый эффект от того, сколько Objects
создано оператором?
Ответ:
1) После этого создается один дополнительный объект.
a) "xyz"
String
создается и интернируется, когда JVM загружает class
, в котором содержится эта строка кода.
- Если
"xyz"
уже находится в основном пуле из какого-либо другого кода, тогда литерал не может создать новый объект String
.
b) Когда создается новый String s
, внутренний char[]
является копией интернированной строки "xyz"
.
c) Это означает, что когда строка выполняется, создается только один дополнительный объект.
Дело в том, что объект "xyz"
будет создан, как только загрузится класс, и до того, как этот раздел кода будет запущен.
... следующий сценарий...
2) Существует три объекта, созданных кодом (включая интернированный "a"
)
String s1 = "a";
String s2 = "a";
String s3 = new String("a");
a) s1 и s2 просто ссылаются, а не объекты, и они указывают на то же самое String
в памяти.
b) "a" интернирован и представляет собой составной объект: один объект char[]
и сам объект String
. Он состоит из двух объектов в памяти.
c) s3, new String("a")
создает еще один объект. Новый String("a")
не копирует char[]
слова "a", он ссылается только на него. Вот подпись метода:
public String2(String original) {
this.value = original.value;
this.hash = original.hash;
}
Один интернированный String
("a")
равен 2 Objects
. И один new String("a")
равен еще одному объекту. Чистый эффект от кода - это три объекта.
Ответ 2
Для этого создаются два объекта:
String s = new String("abc");
Один в куче, а другой в "пуле строковых констант" (SCP). Ссылка s
всегда будет указывать на s
, а GC не разрешена в области SCP, поэтому все объекты в SCP будут автоматически уничтожены во время отключения JVM.
Например:
Здесь, используя ссылку на объект кучи, мы получаем соответствующую ссылку объекта SCP путем вызова intern()
String s1 = new String("abc");
String s2 = s1.intern(); // SCP object reference
System.out.println(s1==s2); // false
String s3 = "abc";
System.out.println(s2==s3); //True s3 reference to SCP object here
Ответ 3
Существует два способа создания строковых объектов в Java:
-
Используя новый оператор, т.е.
String s1 = new String("abc");
-
Использование строкового литерала, т.е.
String s2 = "abc";
Теперь распределение строк является дорогостоящим как во времени, так и в памяти, поэтому JVM (Java Virtual Machine) выполняет некоторые задачи. ЧТО ЗАДАЕТСЯ?
Смотрите, всякий раз, когда вы используете оператор new
, объект создается, а JVM не будет выглядеть в пуле строк. Он просто собирается создать объект, но когда вы используете строковые литералы для создания строковых объектов, JVM выполнит задачу поиска в пуле строк
I.e., когда вы пишете
String s2 = "abc";
JVM будет выглядеть в пуле строк и проверять, существует ли "abc" или нет. Если он существует, возвращается ссылка на уже существующую строку "abc", и новый объект не создается, а если он не существует, создается объект.
Итак, в вашем случае
(А)
String s1 = new String("abc");
- Так как используется
new
, объект создается
(б)
String s2 = "abc";
- с использованием строкового литерала создается объект, а "abc" не находится в
пул строк и, следовательно, объект создан.
(с)
String s2 = "abc";
- Опять же, используя строковый литерал, а "abc" - в пуле строк и
поэтому объект не создается.
Вы также можете проверить это, используя следующий код:
class String_Check
{
public static void main(String[] n)
{
String s1 = new String("abc");
String s2 = "abc";
String s3 = "abc";
if (s1==s2)
System.out.println("s1==s2");
if(s1==s3)
System.out.println("s1==s3");
if(s2==s3)
System.out.println("s2==s3");
}
}
Надеюсь, это поможет... Обратите внимание, что ==
используется, чтобы видеть, равны ли объекты, и метод equals(Object)
используется, чтобы увидеть, соответствуют ли контент.
Ответ 4
-
String s = новая строка ("xyz");
Приведенная выше строка создаст два объекта: один находится в куче, а другой - в пуле констант String.
теперь, если мы сделаем это
-
String s = new String("xyz");
-
String s1 ="xyz";
вышеприведенные два утверждения создадут два объекта. Первая строка String s = new String("xyz");
создаст два объекта, как указано в 1-й строке и, когда String s = "xyz";
выполняет его, проверяет в пуле строковых констант, есть ли там тот же объект содержимого, или нет, так как первая строка сделала запись в пуле строковых констант с помощью "xyz", он возвращает ту же ссылку и не создает другой объект.
Что делать, если у нас есть эти четыре линии вместе, как упоминалось ниже.
-
String s2 = new String("xyz");
-
String s3 ="xyz";
-
String s4 = new String("xyz");
-
String s5 ="xyz";
Если мы выполним вышеуказанную строку, у нас будет три объекта.
- Первый и, как уже упоминалось, создадут два объекта, один в куче, а другой в строковом постоянном опросе.
- Когда вторая строка выполняется, она проверяет строковую константу poll
и найти с помощью "xyz", чтобы он возвращал один и тот же объект, так что до второй строки у нас есть два объекта. - когда третья строка будет выполнена, она создаст новый объект в куче, поскольку оператор new создает объект в куче, поэтому до третьей строки будет 3 объекта.
- Когда выполняется четвертая строка, она проверяет строковую константу poll
и найти с помощью "xyz", чтобы он возвращал один и тот же объект, поэтому в четвертой строке у нас есть три объекта.
Бонус о методе intern()
Когда метод intern() вызывается для объекта String, он ищет строку, содержащуюся в этом объекте String, в пуле, если строка находится там, возвращается строка из пула. В противном случае этот объект String добавляется в пул и возвращается ссылка на этот объект String.
public class TestString {
public static void main(String[] args) {
String s1 = "Test";
String s2 = "Test";
String s3 = new String("Test");
final String s4 = s3.intern();
System.out.println(s1 == s2);
System.out.println(s2 == s3);
System.out.println(s3 == s4);
System.out.println(s1 == s3);
System.out.println(s1 == s4);
System.out.println(s1.equals(s2));
System.out.println(s2.equals(s3));
System.out.println(s3.equals(s4));
System.out.println(s1.equals(s4));
System.out.println(s1.equals(s3));
}
}
Ответ 5
Если мы выполним String s = new String("Brajesh");
должны быть созданы два объекта. Один объект будет создан в строковом литерале, а другой - в области кучи. Но если у нас уже есть тот же строковый литерал объекта, то создается только один объект. лайк
String s1 ="Brajesh";
String s = new String("Brajesh");//it will create only one object in heap area
Помимо этого еще один дополнительный объект также создается в области кучи, который является объектом char []. Я приложил здесь снимок кучи памяти. ![enter image description here]()
Ответ 6
Создаются 2 или 3 объекта, в зависимости от того, насколько интеллектуальным является компилятор.
Тем не менее, ваш тест неактивен, потому что hashCode
of String
основан на содержимом String
, а не на их идентификаторе. Если вы хотите проверить личность, вы должны использовать сравнение System.identityHashCode
или просто ==
.
Компилятор и среда выполнения разрешены (не принудительно) для оптимизации создания строк, когда это возможно. Таким образом, они оптимизируют литеральные строки, используя один литерал для трех строк, которые у вас есть.
Во всяком случае, оператор new
должен возвращать новый объект (т.е. Недавно выделенный).
Оптимизация строк во время выполнения возможна, если вместо этого используется статический метод String.valueOf
. Но я не знаю, действительно ли какое-либо кэширование применяется существующими JRE (возможно, более дорого проверить хэш-таблицу, чем просто выделить новый String
)
Ответ 7
java.lang.String
переопределяет метод hashCode()
, так что значение зависит от содержимого строки.
В результате hashCode()
ничего не говорит о количестве экземпляров. Это может быть одна и та же строка или может быть другим экземпляром без общего байта. То же о equals()
. Это объясняет ваш результат.
Используйте System.identityHashCode(..) для такого рода исследований.
И может быть источник с вами.
Ответ 8
String s1="Pune";
String s2="Mumbai";
String s3="Pune";
String s4=new String("Mumbai");
System.out.println("S1 :"+s1.hashCode()); //S1 :2499228
System.out.println("S2 :"+s2.hashCode()); //S2 :-1979126203
System.out.println("S3 :"+s3.hashCode()); //S3 :2499228
System.out.println("S4 :"+s4.hashCode()); //S4 :-1979126203
System.out.println(s2==s4); // false
Как мы видим в приведенной выше программе, мы получаем одинаковый хэш-код для s2 и s4, хотя мы получаем false с помощью оператора ==. == используется для сравнения ссылок.
В "String s4 = new String (" Mumbai ") были созданы два объекта: один в кучевой памяти и один в стеке. Поэтому s2 сравнивается с s4, который создается в куче памяти, а не с памятью стека.
Ответ 9
public String(String original) {
int size = original.count;
char[] originalValue = original.value;
char[] v;
if (originalValue.length > size) {
// The array representing the String is bigger than the new
// String itself. Perhaps this constructor is being called
// in order to trim the baggage, so make a copy of the array.
int off = original.offset;
v = Arrays.copyOfRange(originalValue, off, off+size);
} else {
// The array representing the String is the same
// size as the String, so no point in making a copy.
v = originalValue;
}
this.offset = 0;
this.count = size;
this.value = v;
}
Если мы увидим код, мы увидим, что он просто создаст char [], и он будет каждый раз копироваться с тем же контентом, который будет создан, и да, он будет хранить данные в String Constant Pool. 1) Возьмем из SCP String s1 = "a" String s2 = "a"; 2) Создает новый объект String s3 = new String ( "a" ); Curiosity, New Object String s2 = new String ( "a" ); Во всем выше кода тот же char [] получит copied.i: e char [] значение Вы можете проверить здесь
Ответ 10
Если мы запустим приведенный ниже код в eclipse в режиме отладки, мы получим представление о том, сколько объектов создано с помощью String string = new String("manoj");
Внутренне он создаст String str = "manoj"
в конструкторе класса String. Просто проверьте идентификатор после наведения на ссылку, как показано на снимке экрана ниже. Скриншот
public static void main(String[] args)
{
String str = "atul";
String string = new String("manoj");
String string2 = "manoj";
System.out.println(str == string);
}
Ответ 11
Запутавшись в том, что именно происходит после вызова новой строки ("<>"), я нашел эту тему. Ваше понимание сравнения хэш-кода не является технически правильным, хотя.
int hashCode() был переопределен в классе String, и он возвращает значение в зависимости от содержимого литерала String.
String s1 = new String ("Hello"); String s2 = new String ("Hello");
Итак, s1.hashCode() = s2.hashCode() = anyStringOfContent_ "Hello".hashCode()
**/** Cache the hash code for the string */
private int hash; // Default to 0
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
**h = 31 * h + val[i];**
}
hash = h;
}
return h;
}**
Теперь, чтобы просто объяснить, почему это сделано, вы можете прочитать книгу Кэти Сьерра, в которой есть отличное объяснение, почему разработчики поступили таким образом (в основном любые объекты, возвращающие true в метод equals(), должны возвращать то же значение hashCode()).
Ответ 12
Если new String() создает 2 объекта (один в куче и один в пуле строк), то какой метод .intern используется?
Метод intern(), вызываемый для объекта String, ищет строку, содержащуюся в этом объекте String, в пуле. Если строка находится там, возвращается строка из пула. В противном случае этот объект String добавляется в пул и возвращается ссылка на этот объект String.
Ответ 13
Я запустил его в отладчике Eclipse. В этом контексте создаются два объекта: один с идентификатором 17, другой 22:
![enter image description here]()
Ответ 14
@Giulio, Вы правы.
String s3 = new String ( "abc" ); создает два объекта один в куче со ссылкой s3 и другой в SCP (без ссылки).
и теперь String s2 = "abc" ; не создает никакого нового объекта в SCP, потому что "abc" уже присутствует в SCP.
String s1 = "abc";
String s2 = "abc";
String s3 = new String("abc");
String s4 = s3.intern();
System.out.println("s1: "+System.identityHashCode(s1));
System.out.println("s2: "+System.identityHashCode(s2));
System.out.println("s3: "+System.identityHashCode(s3));
System.out.println("s4: "+System.identityHashCode(s4));
O/P: s1: 366712642, s2: 366712642, s3: 1829164700, s4: 366712642
Поскольку я не могу комментировать, я написал его здесь.
Ответ 15
В Java существует концепция, называемая пулом строк. Пул строк (пул строк) - это специальная область хранения в куче Java. Когда создается строка и если строка уже существует в пуле, будет возвращена ссылка на существующую строку вместо создания нового объекта и возврата его ссылки.
Итак String s = new String("xyz")
он создаст два объекта.
-
Первый объект будет создан в постоянной памяти кучи Java как часть аргумента, который мы передаем, - "XYZ". И он будет создан в пуле строк String.
-
Второй объект будет создан в памяти кучи Java, который будет создан как часть оператора new
.
Ответ 16
String s = новая строка ("xyz");
сколько объектов было создано в приведенном выше коде?
В приведенном выше коде был создан только один объект, который находится в куче памяти.
не два объекта.....
Если два объекта созданы, один находится в динамической памяти (оператор new), а другой - в пуле String (строковый литерал), если ваше хранилище ниже значения с использованием литерала String,
Строка s1 = "xyz";
он не будет возвращать ссылку на объект s в пуле строковых констант. он создаст новый объект в String Constant Pool как s1.
Как?
мы можем проверить это с помощью оператора == (s == s1), чтобы проверить тип ссылки. Если s уже хранится в пуле строковых констант, он выдает true, в этом случае вывод ложен.
Таким образом, вывод заключается в том, что один объект создан в приведенном выше коде.
Ответ 17
Просто потому, что все ваши хэш-коды одинаковы, это не значит, что вы смотрите на один и тот же объект. Создаются два объекта. Пусть это сломается.
String s = new String("xyz");
В части 'new String ( "xyz" ) адрес возвращается к новой строке "xyz". Когда вы говорите "String s =", это присваивает возвращенный адрес этому объекту, чтобы они указывали на одно и то же место, но новая строка и строка s являются двумя отдельными объектами.
Ответ 18
Я использовал метод hashcode()
для поиска числа созданных строковых объектов.
Метод hashcode()
пересказывает данные, хранящиеся в ссылочной переменной, в одно значение хэша.
case1:
String s="
Fred";
System.out.println(s.hashCode());
s=s+"47";
System.out.println(s.hashCode());
s=s.substring(2,5);
System.out.println(s.hashCode());
s=s.toUpperCase();
System.out.println(s.hashCode());
s=s.toString();
System.out.println(s.hashCode());
Вывод:
Fred--2198155 //1st object ---------------- String s="Fred"
Fred47--2112428622 //2nd object ---------------- s=s+"47"
ed4--100213 //3rd object ---------------- s=s.substring(2,5)
ED4--68469 //4th object ---------------- s=s.toUpperCase()
ED4--68469 //this is retrieved from the string constant pool -------- s=s.toString();
Так создано всего 4 объекта.
CASE 2:
String s="FRED";
System.out.println(s.hashCode());
s=s+"47";
System.out.println(s.hashCode());
s=s.substring(2,5);
System.out.println(s.hashCode());
s=s.toUpperCase();
System.out.println(s.hashCode());
s=s.toString();
System.out.println(s.hashCode());
Вывод:
FRED--2166379 //1st object ---------------- String s="Fred"
FRED47--2081891886 //2nd object ---------------- s=s+"47"
ED4--68469 //3rd object ---------------- s=s.substring(2,5)
ED4--68469 //this is retrieved from the string constant pool ------- s=s.toUpperCase()
ED4--68469 //this is retrieved from the string constant pool -------- s=s.toString()
Всего создано 3 объекта.
Ответ 19
Существует способ найти, сколько объектов создается с помощью ключевого слова new
(String s1=new String("Rajesh")
).
public class Rajesh {
public static void main(String[] args){
String s1=new String("Rajesh");
System.out.println(s1+s1.intern());
}
}
Вывод:
RajeshRajesh //s1=Rajesh+s2.intern()=Rajesh
Примечание. Поскольку мы знаем, что метод intern всегда попадает в строковый постоянный пул памяти кучи.