Darbas su „ArrayStoreException“

 Object[] o = "a;b;c".split(";"); o[0] = 42; 

išmeta

 java.> 

a

 String[] s = "a;b;c".split(";"); Object[] o = new Object[s.length]; for (int i = 0; i < s.length; i++) { o[i] = s[i]; } o[0] = 42; 

ne

Ar yra koks nors kitas būdas išspręsti šią išimtį nesukuriant laikinos masyvo String[] ?

29
11 сент. nustatyti sp00m 11 sep . 2012-09-11 15:40 '12, 15:40 pm 2012-09-11 15:40
@ 4 atsakymai

„Java“ masyvas taip pat yra objektas.

Galite pridėti potipio objektą į supertype kintamąjį. Pavyzdžiui, galite įterpti String objektą į Object kintamąjį.

Deja, „Java“ masyvo apibrėžimas yra kažkaip sugadintas. String[] yra Object[] potipis, tačiau tai negerai! Išsamesnis paaiškinimas yra skaitomas apie „kovariaciją ir kontracepciją“, tačiau toks dalykas yra toks: tipas turėtų būti laikomas kito tipo potipiu tik tuo atveju, jei potipis atitinka visus supertetės įsipareigojimus. Tai reiškia, kad jei vietoj supertype objekto gausite potipio objektą, neturėtumėte tikėtis, kad elgesys prieštaraus supertype sutarčiai.

Problema yra ta, kad String[] palaiko tik dalį sutarties Object[] sutarties. Pavyzdžiui, galite perskaityti Object reikšmes iš Object[] . Taip pat galite perskaityti Object reikšmes (kurios yra String objektai) iš String[] . Viskas vyksta gerai. Problema kyla kitoje sutarties dalyje. Galite įdėti Object į Object[] . Tačiau negalite įkelti Object String[] . Todėl String[] neturėtų būti laikoma Object[] potipiu, tačiau Java specifikacijoje taip sakoma. Ir todėl turime tokių pasekmių.

(Atkreipkite dėmesį, kad panaši situacija vėl pasirodė su įprastomis klasėmis, tačiau šį kartą jis buvo teisingai išspręstas. List<String> nėra List<Object> potipis, ir, jei norite, kad jiems būtų bendras bendrasis tipas, jums reikia List<?> tai yra tik skaitymui, nes ji taip pat turėtų būti su matricomis, bet tai ne. Ir dėl atgalinio suderinamumo per vėlu jį pakeisti.)

Pirmajame pavyzdyje funkcija String.split sukuria String[] objektą. Galite įdėti jį į kintamąjį Object[] , tačiau objektas lieka String[] . Štai kodėl ji atmeta „ Integer vertę. Turite sukurti naują Objects[] ir kopijuoti reikšmes. Galite kopijuoti duomenis naudodami „ System.arraycopy funkciją, tačiau negalite išvengti naujos masyvo kūrimo.

51
11 сент. Atsakymas suteikiamas Viliam Búr 11 sep . 2012-09-11 15:56 '12, 15:56, 2012-09-11 15:56

Ne, nėra jokio būdo vengti kopijuoti masyvo, sugrąžinto per split .

Masyvas, kurį split sugrįžta, iš tikrųjų yra String[] , o „Java“ leidžia priskirti jį Object[] . Tačiau jis vis dar String[] , todėl, kai bandote išsaugoti kažką kitą, išskyrus String , gausite „ ArrayStoreException .

Daugiau informacijos žr. 4.10.3. Subtitravimas tarp masyvo tipų Java kalbos specifikacijoje.

6
11 сент. Atsakymą pateikė Jesper 11 Sep. 2012-09-11 15:44 '12, 13:44 pm 2012-09-11 15:44

Žinoma, yra ir kitų variantų, pavyzdžiui, įgyvendinate savo suskaidytą metodą, kuris grąžina Objekto masyvą tiesiogiai. Nesu tikras, nors tai, kas tikrai trukdo jums laikinai Styginių masyvo?

Beje, galite sumažinti savo kodą keliomis eilutėmis naudodami „System.arrayCopy“, o ne įgyvendinti savo kilpą, kad kopijuotumėte masyvo elementus:

 System.arrayCopy(s, 0, o, 0, s.length); 
0
11 сент. Jrnbjo atsakymas 11 Sep 2012-09-11 16:03 '12 at 4:03 pm 2012-09-11 16:03

Jei jums nereikia naudoti „split“ ... tada galite išvengti kopijavimo ...

-1
11 сент. Atsakymą pateikė Rajan 11 sep. 2012-09-11 16:13 '12, 16:13 2012-09-11 16:13

Kiti klausimai apie žymes arba Užduoti klausimą