Jeśli String jest klasą taką samą jak każda inna, jak można ją zainicjować za pomocą podwójnych cudzysłowów?
java.lang.Stringspecjalne traktowanie języka Java.
Jeśli String jest klasą taką samą jak każda inna, jak można ją zainicjować za pomocą podwójnych cudzysłowów?
java.lang.Stringspecjalne traktowanie języka Java.
Odpowiedzi:
Projektanci Javy zdecydowali się zachować typy prymitywne w języku zorientowanym obiektowo, zamiast czynić wszystko obiektami, aby poprawić wydajność języka. Prymitywy są przechowywane w stosie wywołań, które wymagają mniej miejsca w pamięci i są tańsze w manipulowaniu. Z drugiej strony obiekty są przechowywane w stercie programu, co wymaga złożonego zarządzania pamięcią i większej ilości przestrzeni dyskowej.
Ze względu na wydajność, ciąg Java został zaprojektowany tak, aby znajdował się pomiędzy prymitywem a klasą.
Na przykład
String s1 = "Hello"; // String literal
String s2 = "Hello"; // String literal
String s3 = s1; // same reference
String s4 = new String("Hello"); // String object
String s5 = new String("Hello"); // String object

Uwaga: Literały ciągów są przechowywane we wspólnej puli. Ułatwia to współdzielenie pamięci dla ciągów o tej samej zawartości, aby oszczędzać miejsce. Stringobiekty przydzielone za pośrednictwem nowego operatora są przechowywane w katalogu heapi nie ma współdzielenia magazynu dla tej samej zawartości.
Java traktuje String jako specjalną klasę, możesz zainicjować na dwa sposoby
Bezpośrednie przypisywanie literału
String a = "adsasdf";Podobnie jak inne obiekty przy użyciu nowego słowa kluczowego
String a = new String("adsasdf");Musisz zachować szczególną ostrożność, gdy chcesz porównać ze ==znakiem:
String a = "asdf";
String b = "asdf";
System.out.println(a == b); // True
System.out.println(a.equals(b)); // True
String a = new String("asdf");
String b = new String("asdf");
System.out.println(a == b); // False
System.out.println(a.equals(b)); // True
Dzieje się tak dlatego, że w pierwszym przypadku obiekty a i b są przechowywane w czymś nazywanym literal pooli oba odnoszą się do tego samego obiektu, więc są równe w obu przypadkach.
Ale w drugim przypadku a i b odwołują się do różnych obiektów, tak jak wtedy, gdy inicjalizujemy inne obiekty. więc są nierówne w porównaniu z ==operatorem, podczas gdy mają równe wartości.
String jest traktowany w specjalny sposób w JLS: jest to jeden z dwóch niepierwotnych typów, dla których istnieją literały (drugi to Class) * .
Z JLS :
Literał łańcuchowy to odniesienie do instancji klasy `String [...].
* cóż, istnieje również „typ null” z jego „literałem null” null, ale większość ludzi nie uważa „typu null” za właściwy typ.
nullna przypisanie dowolnego do dowolnej zmiennej typu referencyjnego. W przeciwnym razie to nie jest interesujący typ.
Tekst w cudzysłowie tworzy Stringobiekt literału .
String myString = "Some text";
Powyższy kod tworzy Stringobiekt, używając podwójnych cudzysłowów.
Łańcuchy są bardzo często używane w języku programowania. Ponieważ java jest zorientowana obiektowo, łańcuch jest obiektem. Aby uniknąć uciążliwego nowego ciągu znaków („someString”); instrukcja za każdym razem, gdy potrzebujesz obiektu typu string, java pozwala po prostu utworzyć obiekt typu string przy użyciu literału ciągu.
Należy jednak pamiętać o równości strun. Tutaj krótki test JUnit, aby pokazać, o co mi chodzi.
@Test
public void stringTest() {
// a string literal and a string object created
// with the same literal are equal
assertEquals("string", new String("string"));
// two string literals are the same string object
assertSame("string", "string");
// a string literal is not the same object instance
// as a string object created with the same string literal
assertFalse("string" == new String("string"));
// java's String.intern() method gives you the same
// string object reference for all strings that are equal.
assertSame("string", new String("string").intern());
}
new String(String src), nie byłbyś nawet w stanie nadać konstruktorowi literału ciągu. Musiałbyś zainicjować a char [], a następnie użyć String(char [] src)consructora do skonstruowania łańcucha, albo musiałbyś odczytać łańcuch z pliku.
- String to klasa w Javie . Masz rację, więc zawsze możemy zainicjować za pomocą newsłowa kluczowego.
- Ale kiedy robimy coś takiego:
String s = "";
Powyższa instrukcja jest oznaczana przez kompilator jako specjalny obiekt String, a następnie JVM podczas ładowania klasy (ładowanie odbywa się przed inicjalizacją), widzi to tak zwany literał ciągu , który jest przechowywany w puli literałów ciągu .
- Tak więc String można utworzyć za new()pomocą ""metody i, ale ta ostatnia dostarcza literał ciągu, który pozostaje w stercie nawet wtedy, gdy nie ma odniesienia do tego obiektu ciągu, ponieważ ma odniesienie z puli literałów ciągu.
Java wykonuje dla nas proces dwuetapowy.
String str = "hello";
jest równa
char data[] = {'h', 'e', 'l' , 'l', 'o'};
String str = new String(data);
Podobnie jak [.NET] [1] ma podobną rzecz.
String(Char[]) constructor
robi
String(char[] value)
Dodawanie referencji: -
"hello"jest to literał łańcuchowy i zostanie umieszczony w puli stałej przez kompilator, patrz JLS §3.10.5 i JVMS §5.1 .
Java.lang.Stringto nie tylko klasa. To integralna część podstawowego języka. Kompilator ma do tego cukier syntaktyczny. Na przykład ""jest jak skrót od new String(""). Podczas pisania ""kompilator optymalizuje identyczne ciągi do tej samej instancji, aby zaoszczędzić miejsce."a" + 5 == "a5" ==> true
Kompilator ma cukier składniowy do wielu rzeczy, w tym brak konieczności pakowania / rozpakowywania między wersjami obiektów i ich rodzimymi typami, brak rodzica oznacza Object, domyślny konstruktor, ...
""nie jest skrótem od new String(""). Jeśli używasz "", pierwszą rzeczą, która zostanie zrobiona, jest wyszukanie dopasowań w puli String maszyny JVM i jeśli to prawda, zwróci ten ciąg. Używając new String(""), zawsze utworzysz nowy ciąg, nawet jeśli sam ciąg już istnieje w puli ciągów (ponieważ nie będzie przechowywany w puli ciągów).
" "jest już Stringiem!