五金反引号
五種琴弦
從Java 1.0開(kāi)始,我們就有了字符串文字"like this" 。 我們還想要其他什么字符串? 其他編程語(yǔ)言為我們提供:
- 表達(dá)式插值: s"I am ${age - 10} years old."
- 插值格式: f"Price: $price%8.2f"
- 具有在編譯時(shí)檢查的內(nèi)部語(yǔ)法的字符串: r"[0-9]+([.,][0-9]*)?或xml"<a href='http://java.sun.com'>The Java home page</a>"
- 不轉(zhuǎn)義反斜杠的原始字符串: raw"\.*"
- 可以包含換行符的多行字符串: """ +-----+ | Cay | +-----+ """
在這里,我使用的語(yǔ)法讓人想起Scala進(jìn)行演示。 其他語(yǔ)言則做出了不同的選擇。 例如,JavaScript使用反引號(hào)進(jìn)行插值。
我最喜歡Java中的哪些功能? 對(duì)我而言,這將是編譯時(shí)語(yǔ)法檢查。 現(xiàn)在,IDE可以對(duì)特定的字符串(例如,正則表達(dá)式)進(jìn)行有根據(jù)的猜測(cè),并在其格式錯(cuò)誤時(shí)發(fā)出警告。 但是,如果是編譯時(shí)錯(cuò)誤,那就更好了。
當(dāng)然,這是一個(gè)難題。 除了注釋處理,沒(méi)有其他機(jī)制可以在編譯時(shí)添加可插入檢查。 可以提供檢查字符串內(nèi)容的注釋,實(shí)際上Checker Framework就是這樣做的。 但是您注釋變量,而不是字符串文字,因此不是同一回事。
如果有一種進(jìn)行插值和格式化的標(biāo)準(zhǔn)方法,那也很好。 現(xiàn)在,我們有String.format和MessageFormat.format ,它們都是有用的但不兼容。
相反,Java 12為我們提供了原始/多行字符串。 那也很好
原始字符串
考慮例如使用正則表達(dá)式搜索句點(diǎn)。 正則表達(dá)式為\. 因?yàn)槟仨氃谡齽t表達(dá)式中轉(zhuǎn)義一個(gè)句號(hào)。 因此在Java中,它是Pattern.compile("\\.") 。 為了匹配反斜杠,它是Pattern.compile("\\\\") 。 這會(huì)變得很混亂。
實(shí)際上,它是如此令人困惑,以至于JEP 326的作者弄錯(cuò)了它,或者也許具有微妙的幽默感。 作者的示例是Pattern.compile("\\\"")以匹配" 。 當(dāng)然,您不需要在正則表達(dá)式中進(jìn)行轉(zhuǎn)義,因此Pattern.compile("\"")可以正常工作,這證實(shí)了所有轉(zhuǎn)義都是一團(tuán)糟。
解決方法很簡(jiǎn)單。 將字符串括在反引號(hào)`...` 。 反引號(hào)內(nèi)的所有內(nèi)容都無(wú)需逃脫: Pattern.compile(`\.`)
但是,如果字符串包含反引號(hào)怎么辦?
在Scala和Kotlin中,您使用"""分隔符,但這引出了問(wèn)題。如果字符串包含"""怎么辦?
這是Java設(shè)計(jì)師提出我以前從未見(jiàn)過(guò)的一個(gè)聰明的主意。 您可以使用任意數(shù)量的反引號(hào)來(lái)開(kāi)始一個(gè)原始字符串,然后使用相同數(shù)量的反引號(hào)來(lái)結(jié)束它。 例如,如果您知道您的字符串中沒(méi)有五個(gè)連續(xù)的反引號(hào),請(qǐng)執(zhí)行以下操作:
String s = `````. . . . . . . . . . . .`````; // Five golden backticks :-)字符串中的所有內(nèi)容均照原樣進(jìn)行。 如果它是一些HTML或SQL或您在其他地方開(kāi)發(fā)的任何內(nèi)容,則將其粘貼。
實(shí)際上,“按原樣”是一個(gè)例外。 即使源文件使用Windows風(fēng)格的\r\n行尾,所有行尾都被標(biāo)準(zhǔn)化為\n 。
美中不足的蒼蠅
Stephen Colebourne指出,兩個(gè)反引號(hào)可能會(huì)與空字符串混淆。 如果你有類(lèi)似的東西
s = ``; t = ``;那么就不會(huì)將s和t設(shè)置為空字符串,而是將s設(shè)置為字符串";\nt = " 。
那里有個(gè)很好的謎題。
原始字符串不能以反引號(hào)開(kāi)頭或結(jié)尾。 例如,假設(shè)您要將以下Markdown片段放入Java字符串中:
<
pre>“`
警報(bào)(“ Hello,World!”)
警報(bào)(“ Hello,World!”)
“
“”`.strip();
strip調(diào)用將在開(kāi)頭和結(jié)尾刪除\n 。 或者,也可以將換行符留在原處,如果它們無(wú)關(guān)緊要。
( strip方法是Java 11的新功能。它與trim相似,但是它去除了開(kāi)頭和結(jié)尾的Unicode空白,而trim刪除了≤32的字符,這已經(jīng)不一樣了。這些天,您應(yīng)該使用strip ,而不是trim 。)
IDE支持
激活JDK 12的實(shí)驗(yàn)功能時(shí),IntelliJ 2018.3可以將帶有反斜杠的字符串轉(zhuǎn)換為原始字符串。(有關(guān)詳細(xì)信息,請(qǐng)參閱此博客文章 。)
我嘗試轉(zhuǎn)換老式的多行字符串:
那是行不通的,但是沒(méi)有理由為什么將來(lái)不會(huì)。
壓痕管理
我更喜歡在最左邊的列上排列多行字符串。 例如,
public static void main(String[] args) {String myNameInABox = ` +-----+ | Cay | +-----+`.strip(); System.out.print(myNameInABox);}它使多行字符串從Java代碼中脫穎而出。 它為您放入原始字符串中的所有內(nèi)容提供了足夠的水平空間。
但是,很多人似乎更喜歡將多行字符串的內(nèi)容與Java代碼對(duì)齊的樣式:
...String myNameInABox = `+-----+| Cay |+-----+`.align();System.out.print(myNameInABox);align方法(在Java 12中定義)刪除空格的公共前綴以及空白行的開(kāi)頭和結(jié)尾。
這種方法存在風(fēng)險(xiǎn)。 如果混合使用制表符和空格,則每個(gè)制表符都計(jì)為一個(gè)空格。 在您的IDE中,有些東西看起來(lái)與您對(duì)齊,但與align方法不一致。 當(dāng)然,您的IDE可能會(huì)警告您這種情況。 IntelliJ 2018.3當(dāng)前不這樣做。
未走的路
關(guān)于新功能的許多討論都在“ Amber Spec”郵件列表中進(jìn)行,您可以在http://mail.openjdk.java.net/pipermail/amber-spec-observers/上進(jìn)行觀察,因此您可以看到具有哪些替代品被考慮。
關(guān)于是否應(yīng)該自動(dòng)刪除縮進(jìn)進(jìn)行了激烈的討論。 可以預(yù)見(jiàn),這最終沒(méi)有被采納。
原始字符串中的Unicode轉(zhuǎn)義如何處理? \u0060應(yīng)該是反引號(hào)嗎? 理智盛行,決定“原始意味著原始”。
是否應(yīng)該將兩個(gè)反引號(hào)定為非法,因?yàn)?#96;`可能與空字符串混淆? 不可以,只有一個(gè)簡(jiǎn)單的規(guī)則,即“任何數(shù)量的反引號(hào)”。
在開(kāi)始反引號(hào)之后換行怎么樣? 關(guān)于是否應(yīng)該將其剝離存在一些來(lái)回的意見(jiàn)。 我仍然感到遺憾的是,沒(méi)有對(duì)此問(wèn)題給予更多關(guān)注。 在換行符中添加換行符將解決兩個(gè)問(wèn)題:初始反引號(hào)和最左列的對(duì)齊。
我膽怯地問(wèn),為什么關(guān)閉分隔符不能“至少與打開(kāi)分隔符一樣多的反引號(hào)”(類(lèi)似于Scala),以便原始字符串可以以反引號(hào)結(jié)尾。 不幸的是,我沒(méi)有回應(yīng)。
令人驚訝的是,像這樣的概念上簡(jiǎn)單的功能有多少細(xì)節(jié)。 撇開(kāi)小調(diào),這是一個(gè)非常受歡迎的禮物,正好趕上假期。
翻譯自: https://www.javacodegeeks.com/2018/12/five-golden-backticks.html
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
- 上一篇: 理想汽车最新销量已超过特斯拉 本月销量已
- 下一篇: 返回值是内置类型 不能更改_选择通过更改