Czy w Javie istnieje sposób na napisanie dosłownego ciągu znaków bez konieczności używania cudzysłowów?

111

Załóżmy, że masz literał String zawierający wiele cudzysłowów. Mógłbyś uciec od nich wszystkich, ale jest to ból i trudne do odczytania.

W niektórych językach możesz po prostu to zrobić:

foo = '"Hello, World"';

Jednak w Javie ''jest używany dla chars, więc nie możesz go używać w Stringten sposób. Niektóre języki mają składnię, aby to obejść. Na przykład w pythonie możesz to zrobić:

"""A pretty "convenient" string"""

Czy Java ma coś podobnego?

Mateusz
źródło
Związane z: stackoverflow.com/questions/2678483/…
Michael Mrozek
Ta odpowiedź pokazuje, jak wkleić wielowierszowe ciągi znaków ucieczki w Eclispe.
Jeff Axelrod
2
Aktualizacja 2018: mogą nadejść surowe literały ciągów dla języka Java. Zobacz moją odpowiedź poniżej
VonC
import jackson ObjectMapper then System.out.println(mapperObj.writeValueAsString(mapperObj.readValue(str, Object.class)));
Kervvv
aktualizacja Q4 2018: surowy ciąg znaków jeszcze nie nadchodzi. Zobacz moją zaktualizowaną odpowiedź .
VonC,

Odpowiedzi:

74

Odpowiedź brzmi nie, a dowód znajduje się w specyfikacji języka Java :

  StringLiteral:
   "StringCharacters"

  StringCharacters:
   StringCharacter
   | StringCharacters StringCharacter

  StringCharacter:
   InputCharacter but not " or \
   | EscapeSequence

Jak widać, StringLiteralmoże być po prostu związany "i nie może zawierać znaków specjalnych bez znaków specjalnych.

Na marginesie: możesz osadzić Groovy w swoim projekcie, to rozszerzy składnię Java, umożliwiając korzystanie z niej '''multi line string ''', ' "string with single quotes" 'a także "string with ${variable}".

Jacek
źródło
141

Nie, i zawsze denerwował mnie brak różnych składni w języku Java.

Oto sztuczka, której używam od czasu do czasu:

String myString = "using `backticks` instead of quotes".replace('`', '"');

Robię coś takiego głównie dla pola statycznego. Ponieważ jest statyczny, kod zastępujący ciąg jest wywoływany raz, podczas inicjalizacji klasy. Tak więc spadek wydajności w czasie wykonywania praktycznie nie istnieje, a kod jest znacznie bardziej czytelny.

benjismith
źródło
czy nie musiałbyś używać replaceAll?
Landon Kuhn
10
@ landon9720 Nie, .replace zastępuje wszystkie wystąpienia ciągu znaków / znaków inną sekwencją znaków / znaków. .replaceAll używa wyrażenia regularnego.
abelito,
Czy z ciekawości wiesz, czy kompilator javy uprościłby to podczas kompilacji?
ug_
2
Nie, nie sądzę, żeby kompilator to uprościł. Ale to nie ma znaczenia. Jest to bardzo niedrogie wywołanie i jeśli zrobię to tylko dla statycznych ciągów końcowych, koszt zostanie poniesiony tylko raz, podczas ładowania klasy. To cena, którą zwykle jestem gotów zapłacić za ładniejszy kod :)
benjismith
3
A co z „\” w myString?
Anderson,
10

Aktualizacja grudzień 2018 (12 miesięcy później):

Surowe literały ciągów (które są na bursztynowej liście ) nie dotrą do JDK 12.
Zobacz krytykę tutaj .


Może istnieć w przyszłej wersji Java (10 lub więcej).

Zobacz JEPS 8196004 ze stycznia 2018 r .: ( „JEP” to „Program ulepszeń JDK” )

Szkic JEP: Surowe literały strunowe

Dodaj nowy rodzaj literału, surowy literał ciągu, do języka programowania Java.
Podobnie jak w przypadku tradycyjnego literału ciągu, surowy literał ciągu tworzy ciąg, ale nie interpretuje ciągów znaków ucieczki i może obejmować wiele wierszy kodu źródłowego .

Więc zamiast:

Runtime.getRuntime().exec("\"C:\\Program Files\\foo\" bar");
String html = "<html>\n"
              "    <body>\n" +
              "         <p>Hello World.</p>\n" +
              "    </body>\n" +
              "</html>\n";
System.out.println("this".matches("\\w\\w\\w\\w"));

Możesz wpisać:

Runtime.getRuntime().exec(`"C:\Program Files\foo" bar"`);
    
String html = `<html>
                   <body>
                       <p>Hello World.</p>
                   </body>
               </html>
              `;

System.out.println("this".matches(`\w\w\w\w`));

Schludny!

Ale to wciąż jest tylko szkic : będzie musiał zostać wysłany, przesłany, być kandydatem i sfinansowany, zanim zostanie ukończony i trafi do następnego JDK.

VonC
źródło
5

Prosta odpowiedź: nie.

W przypadku dłuższych ciągów znaków, których należy unikać, zwykle czytam je z jakiegoś zewnętrznego źródła.

Chris Lercher
źródło
4

możesz także użyć StringEscapeUtils z apache commons

AKTUALIZACJA : Jeśli ktoś jest zainteresowany kilkoma przykładami, to przydatny link: https://dzone.com/articles/commons-lang-3-improved-and-powerful-StringEscapeUtils

Doua Beri
źródło
2
Czy mógłbyś dodać przykład oparty na pytaniu ilustrującym, jak to zrobić w przypadku tego problemu?
Bengt
3
Uważa się, że nieoptymalne jest odwoływanie się tylko do innego zasobu, który może odpowiedzieć na pytanie. Rozważ podsumowanie połączonej strony z przykładem pasującym do pytania.
Bengt
Spojrzałem i nie sądzę, że żadna z nich naprawdę odpowiada na pytanie. Dane wejściowe do metod statycznych to Strings, więc nie ma możliwości umieszczenia w kodzie ładnie sformatowanej wartości. Przypuszczalnie można by użyć tych metod do odczytu z pliku do a String, ale nie sądzę, aby o to tutaj chodziło.
Tom Harrison,
Połączona klasa (org.apache.commons.lang3.StringEscapeUtils) została wycofana i zastąpiona przez org.apache.commons.text.StringEscapeUtils
jcarter
-4

Wydaje mi się, że działa dla mnie:

String x = "Some Text" + '"' + "More Text" + '"' + "Even More Text";

Myślę, że ponieważ char jest pierwotnym typem zmiennej dla ciągu znaków, można łączyć ciągi znaków i znaki (przynajmniej kompilator eclipse nie wydaje się narzekać).

Osoba anonimowa
źródło
1
Myślę, że ponieważ char jest pierwotnym typem zmiennej dla String <- Twoje założenie jest nieprawidłowe. W tym przypadku zadziała również z innym typem, takim jak int, na przykład: String x = "Jakiś tekst" + 33 + "Więcej tekstu";
Najeeb
-6

Jeśli chcesz uciec 'lub "w swoim ciągu, możesz użyć następującego kodu:

String text = ...

text = text.replaceAll("('|\")", "\\\\$1");
SreejithVS
źródło
Pytanie zadawane o literały łańcuchowe w kodzie źródłowym. Przepraszamy, spróbuj jeszcze raz.
michaelb958 - GoFundMonica