PDA

View Full Version : [Java]Array Exception


Killer Application
13-02-2008, 17:07
Sto progettando un piccolo software per l'università e mi è venuto fuori questo errore


ArrayIndexOutOfBoundsException:
at java.lang.reflect.Array.get(Native Method)


ho letto su internet che appare se si vuole mettere un valore all'interno di una posizione di un array che non esiste;
ad esempio se voglio mettere qualcosa nella posizione 10 di un array che arriva al massimo a 8.


Qualcuno mi puo spiegare meglio questo errore?
(perche non credo di aver fatto un errore tanto stupido)

Grazie:D

banryu79
13-02-2008, 17:11
Documentazione ufficiale SUN :

-> javadoc for class ArrayIndexOutOfBoundsException (http://java.sun.com/j2se/1.4.2/docs/api/java/lang/ArrayIndexOutOfBoundsException.html)


public class ArrayIndexOutOfBoundsException
extends IndexOutOfBoundsException

Thrown to indicate that an array has been accessed with an illegal index. The index is either negative or greater than or equal to the size of the array.


Tradotto: E' un'eccezione che viene lanciata per indicare un tentativo di accesso all'array stesso tramite un indice illegale.
L'indice è illegale perchè è un numero negativo oppure perchè è un numero uguale o maggiore al "size" (alla dimensione) dell'array.

Ciao :)

geko84k
13-02-2008, 21:55
se poi nn riesci a trovare l'errore posta il codice e vediamo... ciao :D

JuliusIT
14-02-2008, 07:28
A volte capita perchè non si considera che l'indice di array e collection inizia da 0 e non da 1.

Killer Application
14-02-2008, 10:39
ho perso la testa mezza serata e non ho tolto un ragno dal buco.

ho ricontrollato tutti i for i if del caso ma nada....


Ho controllato anche l'errore dell'inizio dell'array come suggerito (ovvero che parte da 0) ma niente.

a questo punto non so che fare!
se qualcuno mi puo dare una mano in pvt ne sarei grato, perche non posso postare il codice in pubblico.


Ah non vi spaventate sono giusto una 40 di linee di codice per ora quindi niente di che:D

FedeX_65246X
14-02-2008, 11:07
Se e' un'applicazione multithread probabilmente due o piu'
thread stanno accedendo in modo concorrente alla stessa struttura dati senza un'opportuna sincronizzazione.

Per esempio un thread rimuove un elemento mentre un altro cerca di recuperare lo stesso elemento (credendo sia ancora nella struttura).

lovaz
14-02-2008, 11:11
Ho controllato anche l'errore dell'inizio dell'array come suggerito (ovvero che parte da 0) ma niente.
potrebbe anche essere alla fine, fino a dove arrivi?

Killer Application
14-02-2008, 11:15
Se e' un'applicazione multithread probabilmente due o piu'
thread stanno accedendo in modo concorrente alla stessa struttura dati senza un'opportuna sincronizzazione.

Per esempio un thread rimuove un elemento mentre un altro cerca di recuperare lo stesso elemento (credendo sia ancora nella struttura).

ecco questa cosa non la sapevo e credo che sia proprio questo il guaio, infatti nel mio programma ci sono un paio di funzioni che agiscono su una stessa matrice.

però non so come venirne a capo, cioè ho capito l'errore ma non so come risolverlo:D :muro:

lovaz
14-02-2008, 11:16
Ma in questo caso perche' lancia ArrayIndexOutOfBoundsException,
che non c'entra una?

Killer Application
14-02-2008, 11:17
potrebbe anche essere alla fine, fino a dove arrivi?

questa non l'ho capita:D

aspetta credo di aver capito cio che dici, allora mettiamo che creo una matrice[10]

l'ultimo elemento di essa sarà matrice[9].



era questo quello che intendevi?

lovaz
14-02-2008, 11:22
Esatto, quella ecc. viene lanciata se usi un indice <0 o >=dimensione

FedeX_65246X
14-02-2008, 11:30
Ma in questo caso perche' lancia ArrayIndexOutOfBoundsException,
che non c'entra una?

Thread1: controllo dimensione array, t1_size = M
Thread2: rimuovo elemento n, t2_size = M - 1
Thread1: recupero ultimo elemento,
get(t1_size-1) = get (M-1)

OutOfBoundEx

Killer Application
14-02-2008, 11:33
Esatto, quella ecc. viene lanciata se usi un indice <0 o >=dimensione

ma il fatto è che ho controllato, ma adesso mi sorge un dubbio.

supponiamo sta stringa

matrice è una string

matrice[9]="14";

int idi = Integer.parseInt(matrice[9]);
for(int i = 0; i<10;i++){
if (matrice_appoggio[i][idi]!="//"){
matrice_appoggio[i][idi]=matrice[3]
};
};

il comando integer.parseInt estrae dalla matrice[9] il numero e lo mette come int in "idi" giusto?

Killer Application
14-02-2008, 11:35
Thread1: controllo dimensione array, t1_size = M
Thread2: rimuovo elemento n, t2_size = M - 1
Thread1: recupero ultimo elemento,
get(t1_size-1) = get (M-1)

OutOfBoundEx

posso mandarti un pm con il codice?:help:

perche credo sia questo l'errore ma non riesco a trovarlo

banryu79
14-02-2008, 13:03
Potresti sempre sostituire gli array di primitive (o di String) che usi nel codice con dei Vector (di primitive o di String), dato che la classe Vector è syncronized...

Inoltre se usi un Iterator per scandire il Vector, in caso qualche altro thread tenti di accedere al Vector per modificarlo parte una bella ConcurrentModificationException e così sai che il problema è quello.

andbin
14-02-2008, 13:20
dato che la classe Vector è syncronized...Sì ma questo non elimina tutti i problemi!! Cioè il fatto che una collezione sia synchronized vuol solo dire che la mutua esclusione è sulla singola invocazione di 1 metodo.

Se su una collezione si devono fare operazioni composte, del tipo check-then-act o read-modify-write, allora anche se la collezione in sé è synchronized, la sequenza va fatta in modo atomico e quindi è necessario effettuare il client-side locking, se la collezione lo permette.

Killer Application
14-02-2008, 13:33
rignrazio per i consigli ma sono ancora a uno step base si java.

quindi ancora niente vector, e il prof consiglia di usare gli strumenti utilizzati in classe.

banryu79
14-02-2008, 14:13
Se su una collezione si devono fare operazioni composte, del tipo check-then-act o read-modify-write, allora anche se la collezione in sé è synchronized, la sequenza va fatta in modo atomico e quindi è necessario effettuare il client-side locking, se la collezione lo permette.

Daccordo, ma usando per esempio un'ArrayList al posto degli array e manipolando le istanze della collection solo attraverso l'Iterator può comunque verificare se viene lanciata una ConcurentModificationException...

Questo a patto che le manipolazioni desiderate (scusate l'espressione un poco ambigua :D ) possano essere interamente implementate usando solo l'Iterator, giusto?

Non ho capito tutte le implicazioni della tua osservazione circa il fatto che se anche la collection fosse syncronized sarebbe comunque neccessario fornire altre garanzie: basterebbe per esempio sincronizzare l'intero metodo che opera sulla collection stessa, per esempio? (dove posso documentarmi nello specifico?)

andbin
14-02-2008, 14:40
Daccordo, ma usando per esempio un'ArrayList al posto degli array e manipolando le istanze della collection solo attraverso l'Iterator può comunque verificare se viene lanciata una ConcurentModificationException...Qui ci sarebbero da dire altre cose, ad esempio che il comportamento "fail-fast" degli iteratori nelle principali collezioni di base non è garantito al 100%. Cioè per come è stato implementato, se un thread concorrente modifica la collezione, potrebbe anche capitare che l'iteratore non se ne accorga.
Quindi il comportamento fail-fast è da usare solo per rilevare dei bug, cioè appunto se sbuca fuori un ConcurrentModificationException, allora è un bug e basta.

Non ho capito tutte le implicazioni della tua osservazione circa il fatto che se anche la collection fosse syncronized sarebbe comunque neccessario fornire altre garanzie: basterebbe per esempio sincronizzare l'intero metodo che opera sulla collection stessa, per esempio? (dove posso documentarmi nello specifico?)Per fare un esempio, se voglio eliminare l'ultimo elemento di un Vector (e non c'è infatti un singolo metodo synchronized apposito per questo), dovrei fare:

Vector v = .....

synchronized (v) {
int size = v.size ();
if (size > 0)
v.remove (size-1);
}
Tutta la sequenza deve essere atomica, per questo va fatta tenendo il lock per tutta la sequenza. Che poi lo faccia come blocco synchronized o come metodo synchronized, è indifferente. Ma va fatto, nonostante i singoli metodi di Vector siano synchronized!

^TiGeRShArK^
14-02-2008, 15:13
e comunque è consigliato utilizzare al posto delle vecchie classi che implementano synchronized (come Vector) le nuove classi (come ArrayList) wrappandole con Collections.synchronizedList(List<T> list) :p

banryu79
14-02-2008, 15:15
Per fare un esempio, se voglio eliminare l'ultimo elemento di un Vector (e non c'è infatti un singolo metodo synchronized apposito per questo), dovrei fare:

Vector v = .....

synchronized (v) {
int size = v.size ();
if (size > 0)
v.remove (size-1);
}
Tutta la sequenza deve essere atomica, per questo va fatta tenendo il lock per tutta la sequenza. Che poi lo faccia come blocco synchronized o come metodo synchronized, è indifferente. Ma va fatto, nonostante i singoli metodi di Vector siano synchronized!

Capito, nel frattempo mi sono spulcito qualcosa anche online e il tuo qui presente esempio è stato la ciliegina sulla torta.

A proposito, grazie infinite per la disponibilità dimostrata e la chiarezza :)

lovaz
14-02-2008, 16:41
Thread1: controllo dimensione array, t1_size = M
Thread2: rimuovo elemento n, t2_size = M - 1
Thread1: recupero ultimo elemento,
get(t1_size-1) = get (M-1)

OutOfBoundEx

Rimuovo elemento? Da un array?