Паводзіны Радковыя литералы блытае

Паводзіны радковых литералов вельмі заблытаная ў кодзе ніжэй.

Я магу зразумець, лінія 1, лінія 2 і лінія 3 з'яўляюцца True , але чаму радок 4 хлусня ?

Пры друку на хэш абодвух яны аднолькавыя.

class Hello
{
   public static void main(String[] args)
   {
      String hello = "Hello", lo = "lo";
      System.out.print((Other1.hello == hello) + " ");     //line 1
      System.out.print((Other1.hello == "Hello") + " ");   //line 2
      System.out.print((hello == ("Hel"+"lo")) + " ");       //line 3
      System.out.print((hello == ("Hel"+lo)) + " ");         //line 4
      System.out.println(hello == ("Hel"+lo).intern());      //line 5
      System.out.println(("Hel"+lo).hashCode());   //hashcode is 69609650 (machine depedent)
      System.out.println("Hello".hashCode());       //hashcode is same WHY ??.
   }
}

class Other1 { static String hello = "Hello"; }

Я ведаю, што == правярае роўнасць спасылак і праверыць у басейне для литералов. Я ведаю, што роўны() гэта правільны шлях. Я хачу зразумець гэтую канцэпцыю.

Я ўжо праверыў гэта пытанне , але гэта не тлумачыць ясна.

Я хацеў бы атрымаць поўнае тлумачэнне.

30
Паколькі хэш-код роўнасць не азначае ідэнтычнасць аб'екта. Глядзіце Javadoc для Object.hashCode ().
дададзена аўтар EJP, крыніца
+1 за цікаўнасць .. добры першае пытанне
дададзена аўтар sanbhat, крыніца
Калі вы гэта ведалі, вы б не выклікалі рэзананс Cascade сцэнар!
дададзена аўтар Alex, крыніца

11 адказы

Кожны падчас кампіляцыі канстанты , што мае тыпу Радок будзе ўведзена ў струнным басейн.

Па сутнасці, гэта азначае, што: калі кампілятар можа (лёгка) «вылічыць» значэнне Радок без запуску праграмы, то ён будзе пастаўлены ў басейн (правілы крыху больш складана, чым гэта, і некалькі кутніх выпадкаў, см спасылку вышэй для ўсіх дэталяў).

Гэта дакладна для ўсіх радкоў у радках 1-3.

"Hel"+lo is not a compile-time constant expression, because lo is a non-constant variable.

У хэш-коды аднолькавыя, таму што хэш-код з радка залежыць толькі ад яго ўтрымання . Гэта патрабуецца, па дамове роўны() і хэш-код() .

26
дададзена
Не, каб зрабіць добрае дадатак прадукцыйнасці вы мера , што запавольвае і аптымізаваць <�я>, што . Я зрабіў гэта некалькі разоў, і я пытанне, калі Радок з'яўляецца пастаяннай або няма ніколі не была часткай праблемы прадукцыйнасці. Стварэнне занадта шмат Радок аб'екты па канкатэнацыі у цыкле <�я> мог лёгка </я> быць праблемай, але гэта не (ІМХО), звязаныя з гэтым пытаннем.
дададзена аўтар Joachim Sauer, крыніца
«Колькі аб'ектаў фармуюцца» з'яўляецца ... даволі дрэнна вызначаны пытанне, і, шчыра кажучы толькі калі-небудзь цікава настаўніку ;-) Радкі ў пастаянным пуле таксама аб'екты, і яны таксама атрымліваюць створаны ў некаторы кропка. Калі лічыць іх ці не? Я не ведаю.
дададзена аўтар Joachim Sauer, крыніца
Літаральнае, такія як «Hello» гэта заўсёды канстанта часу кампіляцыі, таму гэта будзе ўзята з пастаяннага пула.
дададзена аўтар Joachim Sauer, крыніца
Як наконт рашэнняў вось канчатковым.
дададзена аўтар Alvin Wong, крыніца
Разлічваеце Ці вы адзін радок, як адзін ці два (сама радок і яе паўкокс [])?
дададзена аўтар Alpedar, крыніца
ок я хачу clearify яшчэ адну рэч, калі мы будзем рабіць, як «Hello» у праграме або калі ўмова, то будзе новы аб'ект або литерал ??
дададзена аўтар user2416387, крыніца
добра, што гэта добра, скажам, калі гаворка ідзе пра тое, як утворыцца шмат аб'ектаў, то я рабіць, калі (прывітанне == «Прывітанне»), так што, калі я тыпу «Hello» яго не аб'ект, і час кампіляцыі літаральным і захоўваюцца ў басейн, праўда?
дададзена аўтар user2416387, крыніца
ну тады я не як працаваць, бо зрабіць добрую прадукцыйнасць прыкладання, вы павінны ведаць, колькі аб'ектаў ствараюцца падчас выканання, я выкарыстоўваю профилировщик ў зацьменні, але я хачу ведаць, як мы можам лічыць гэта падчас кампіляцыі, як Oracle пытаецца OCPJP сертыфікацыя, яны хочуць, каб мы ведалі, што !! У любым выпадку дзякуй, ур анс вялікая і лёгка зразумець,
дададзена аўтар user2416387, крыніца
правільна для гэтага мы павінны зразумець канцэпцыю, што, калі ён збіраецца зрабіць гэта аб'ект і пастаянная !! , Таму, калі гаворка ідзе пра тое, як ствараюцца многія аб'екты, я не кажу, што колькі аб'ектаў сапраўды зроблены ў аператыўнай памяці, яго не магчыма для нас, каб ведаць гэта дакладна, але я меў на ўвазе, што, як мы можам ведаць, што «Hello» з'яўляецца пастаянны літаральны або аб'ект будзе створаны для таго, String в е = новы String ( «Hello»); гэта, безумоўна, з'яўляецца аб'ектам, таму «Hello» з'яўляецца аб'ектам, створаным, але падчас кампіляцыі ён прымае гэта як пастаянная, яна ўспрымае яго як аб'ект падчас кампіляцыі
дададзена аўтар user2416387, крыніца
@AlvinWong добра дазваляе паспрабаваць што
дададзена аўтар user2416387, крыніца

Радкі, вылічаныя падчас выканання канкатэнацыі ствараюцца зноў, і таму розныя

here is a link to read: http://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.10.5

2
дададзена
добра, тут ёсць прамая спасылка на старонку ў кнізе.
дададзена аўтар Chechulin, крыніца
які downvoted гэты каментар, я думаю, што гэта правільна, @JoachimSauer вы глядзіце !!
дададзена аўтар user2416387, крыніца

Гэта таму, што comipler ў дадзеным выпадку не дастаткова разумная, каб зразумець, што ён можа гарэць у адной і той жа радка литерала.

Hashcode павінен заўсёды вяртаць тое ж значэнне для радкоў, якія equivelent (выклік .equals на гэта вяртае ісціну), так будзе вяртаць адзін і той жа вынік.

1
дададзена
stackoverflow.com/questions/3029244/are-strings-created-with‌ -concatenation-крама & ZWNJ; д-в-струннай-пул ж тут напісана
дададзена аўтар ManMohan Vyas, крыніца

Аб'ект Радок можа быць створаны наступным чынам:

String str = new String("abcd"); //Using the new operator 
                                 //str is assigned with "abcd" value at compile time.

String str="abcd";        //Using string literal
                          //str is assigned with "abcd" value at compile time.

String str="ab" + "cd";   //Using string constant expression.
                          //str is assigned with "abcd" value at compile time.
String str1 = "cd";
String str = "ab"+str1;   //Using string expression.
                          //str is assigned with "abcd" value at run time only.

і Hashcode будзе разлічвацца толькі падчас выканання на аснове змесціва аб'ектаў String.

1
дададзена

Як вы ўжо ведаеце ... гэта проста з-за спасылкі ... калі радок прыходзіць з пула будзе мець той жа refrence ... але калі і рабіць manuplations новая радок з новым refrence генеруецца ...

Вы можаце праверыць гэтую спасылку пулинговой

0
дададзена
Праверце Ліны дадзеныя ў адрэдагаванае паведамленні
дададзена аўтар ManMohan Vyas, крыніца
@sanbhat +1 на ваш каментар
дададзена аўтар Saurabh, крыніца
то, як яна ўжываецца для прывітання == ( «Хель» + «з») -> праўды?
дададзена аўтар sanbhat, крыніца
Не маглі б вы пайсці больш у глыбіню. Я не ўпэўнены, што вы правільна
дададзена аўтар Craig, крыніца
КІ ў Line3 я раблю маніпуляцыю «Хель» + «з» створыць новы аб'ект, але ён да гэтага часу называе «Hello» Радок у басейне і калі «Хель» + вось, вось гэта дадаецца радок пераменны, яна будзе ствараць «Hello» то чаму гэта не адносіцца да аднаго пулу літаральным ??
дададзена аўтар user2416387, крыніца

Яго, таму што наступны код

("Hel"+lo)) + " "

перакладаецца ўнутрана

new StringBuilder("Helo").append(new String(lo)).append(new String(" ")).toString()

Такім чынам, вы можаце бачыць, што цалкам новы асобнік радкі ствараюцца з дапамогай розных асобнікаў String. Вось чаму вы атрымаеце ілжывыя, паколькі яны паказваюць на розныя ячэйкі памяці ў кучы

0
дададзена
@saury: дэкампіляцыя можа быць карысна, каб убачыць «што», але ён рэдка адказвае на «чаму».
дададзена аўтар Joachim Sauer, крыніца
@sanbhat Я згодны
дададзена аўтар Saurabh, крыніца
Дарэчы вы спрабавалі ўбачыць дэкампіляваць код? Можа быць, гэта можа праліць некаторы святло ??
дададзена аўтар Saurabh, крыніца
Тады як (прывітанне == ( "Хель" + "з")) + "" -> праўды? :-) Нават тут дадатковая радок дадаецца
дададзена аўтар sanbhat, крыніца
няправільна «» не атрымлівае ўводны, я правяраць перад канкатэнацыяй см брекетов
дададзена аўтар user2416387, крыніца

Хэш-код не мае нічога агульнага з аб'ектамі спасылкай (Праверка == з'яўляецца спасылкай кампаратара). Яго можна мець 2 аб'екта, дзе хэш-код вяртае тое ж значэнне, аператар вяртае роўна дакладна, але == вяртае хлусня. Гэта калі яны 2 розныя аб'екты, але з тым жа значэннем.

Я лічу, што прычына лінія 4 вяртаецца хлусня, што гэта значэнне вылічаецца падчас выканання, і, такім чынам, гэта іншае асобнік радкі, з другога спасылкай.

0
дададзена
Радок прывітанне = «Hello» будзе зроблена падчас кампіляцыі, таму што кампілятар ведае, да таго, як код выконваецца, значэнне ( «Hello»), які павінен ісці ў гэты радок.
дададзена аўтар Ren, крыніца
хмм даволі добра, таму падчас кампіляцыі, ён правярае ў радку басейн, але калі справа даходзіць да апрацоўкі радкоў з Іа, ён будзе правяраць падчас выканання, то радок прывітанне = "Hello" таксама павінны быць правераны падчас выканання, правільна ??
дададзена аўтар user2416387, крыніца

Радковыя литералы захоўваюцца ў спецыяльнай памяці, калі яны сапраўды такія ж, яны паказваюць на тую ж карту памяці. Калі вы не ствараеце літаральна радок, новы аб'ект будзе створаны, таму ён не будзе паказваць на гэтую памяць, так што спасылка не будзе такім жа.

Метад стажор() кажа віртуальную машыну, каб змясціць яго ў гэтую агульную, радковыя литералы карце памяці, так у наступны раз, калі вы што літаральным, ён будзе шукаць там, і паказаць яго.

0
дададзена

Розніца паміж лікам ліній 3 і 4 наступным чынам.

• Радкі, вылічаныя канстантнасцю выразамі вылічаюцца падчас кампіляцыі, а затым апрацоўвалі, як калі б яны былі литералы.

• Радок, вылічэнні канкатэнацыяй падчас выканання ствараецца зноў і, такім чынам, розныя.

Вышэй спасылка бярэцца з спецыфікацыі Java. Калі ласка, дайце мне ведаць, калі вам трэба больш тлумачэнняў.

http://docs.oracle .com/JavaSE/функцыі/JLS/SE7/html/JLS-3.html # ПСБ-3.10.5

0
дададзена
хмм я атрымаў яго, яго бардак са радкамі !!
дададзена аўтар user2416387, крыніца

Нарэшце, я ведаю адказ!

Чытайце Java SE 8 спецыфікацыі раздзел 15.21.3 роўнасць спасылак Аператары == і! = ( http://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.21.3 )

<�Р> У той час як == можа быць выкарыстаны для параўнання спасылак тыпу String, такіх   праверка на роўнасць вызначае, ці будзе два аперанда ставяцца да   Радок жа аб'ект. </Р>      <�Р> Вынік <�моцны> ілжыва </моцны>, калі аперанды <�моцны> розныя </моцны>   Радковыя аб'екты, <�моцны>, нават калі яны ўтрымліваюць тую ж паслядоўнасць сімвалаў (§3.10.5). Змест двух радкоў з і т могуць быць правераны на   роўнасць з дапамогай выкліку метаду s.equals (т). </р>

Такім чынам, наступны код:

class Test {
    public static void main(String[] args) {
        String hello = "Hello";
        String lo = "lo";
        System.out.println((hello == ("Hel"+lo)));//line 3
    }
}

Заявы ( «Хель» + ЛО) у радку 3, вяртаюць новыя радкі, якія вылічаных канкатэнацыя пры падчас выканання .

<�Р> * Радок, вылічэнні канкатэнацыяй пры падчас выканання з'яўляюцца зноў створанымі і таму розныя.   ( http://docs.oracle.com/ JavaSE/функцыі/JLS/SE8/HTML/JLS-3.html # d5e1634 ) </р>

Такім чынам, у выніку гэтага кода:

class Test {
    public static void main(String[] args) {
        String hello = "Hello";
        String lo = "lo";
        System.out.println((hello == ("Hel"+lo)));//line 3
    }
}

прывядзе:

false

Таму што,

«Добры дзень» аб'ект у гэтай заяве:

String hello = "Hello";

і ( «Хель» + с) аб'ект у гэтай заяве:

System.out.print((hello == ("Hel"+lo)) + " ");

з'яўляецца <�моцны> розныя , хоць:

<�Р> * яны абодва ўтрымліваюць адзін і той жа характар, паслядоўнасць, якая з'яўляецца «Hello». </Р>      <�Р> * яны абодва маюць адзін і той жа хэш-код. </Р>      <�Р> * hello.equals (( "Хель" + се)) вяртае ісціну.
0
дададзена

System.identityHashCode() would be returned by the default method hashCode(), this is typically implemented by converting the internal address of the object into an integer.

0
дададзена
<�Код> Радок перавызначаем Object рэалізацыя Hashcode .
дададзена аўтар mkl, крыніца
Зусім правільна, хэш-код для радкі вылічаецца па значэнні.
дададзена аўтар Monster, крыніца