|
|
|
![]() |
|
Strumenti |
![]() |
#1 |
Senior Member
Iscritto dal: Feb 2009
Messaggi: 700
|
[JAVA] Problema in compilazione, messaggio di attenzione operazione insicura, perchè?
Ciao,
stò scrivendo questa classe Java chiamata Involucro che gestisce una collezione di stringhe rappresentate con un Vector. Le stringhe accettate dalla collezione hanno la particolarità che la i-esima stringa deve sempre essere contenuta nella (i+1)-esima stringa. Quindi saranno collezioni del tipo: {a, ab, abc, z[b]abc]u} tanto per fare un esempio. Per ora ho scritto solo il costruttore ed un metodo che aggiunge un elemento alla collezione, tale secondo metodo controlla se la collezione è vuota ci inserisce una stringa ricevuta come parametro, se invece la collezione non è vuota controlla se l'ultimo elemento della collezione è contenuto nel parametro e se è vero lo aggiunge, altrimenti solleva un'eccezione...però mi dà uno strano messaggio in compilazione. Il codice è questo: Classe Involucro (c'è un sacco di documentazione ma quella è perchè piace alla proff, in realtà sono 3 righe di codice): Codice:
import java.util.*; public class Involucro{ /** OVERVIEW: Involucro rappresenta una collezione dinamica di stringhe del tipo <s1, s2, s3,...., sn> tali che s_i è completamente contenuta in s_(i+1). V = {{s1,s2,s3,...,sn>: Per ogni i s_i è una stringa ed s_i è interamente contenuto in s_(i+1)}} O = inserisci: Se l'oggetto che si vuole inserire è coerente con la rappresentazione della collezione (è una stringa) e con lo stato attuale della collezione (i valori già presenti nella collezione), allora lo inserisce nella collezione modificandola fondi: Date collezioni S e T se s_n è interamente contenuto in t_1 allora fonde le due collezioni nel seguente modo: S = <s1,s2,s3,...,sn> T = {t1,t2,t3,...,tn} --> {s1,s2,s3,...,sn,t1,t2,t3,..,tn} get(i): Accede in maniera posizionale all'i-esimo elemento della collezione */ Vector collStr; // Rappresenta la collezione di stringhe /** FUNZIONE DI ASTRAZIONE: F_a(): STATO CONCRETO ----> STATO ASTRATTO F_a([a, ab, abc, abcd]) ------> {<a, ab, abc, abcd>} ma anche: F_a([a, b(a), (ba)f, z(baf), (zbaf)e]) ---> {a, ba, baf, zbaf, zbafe} INVARIANTE DI RAPPRESENTAZIONE: è un predicato I: C ---> boolean che è vero per gli stati concreti che sono rappresentazioni leggittime di uno stato astratto: I(collStr): collStr != NULL (il Vector deve essere sempre diverso da NULL) Per ogni i: v.get(i) deve essere incluso in v.get(i+1) (la i-esima stringa deve sempre essere interamente contenuta nella (i+1)-esima stringa della collezione */ /** COSTRUTTORE: EFFECTS: Crea un nuovo oggetto di tipo Involucro che rappresenta la collezione vuota @param: void: @return: Il riferimento ad un oggetto di tipo Involucro Il costruttore soddisfa l'invariante di rappresentazione in quanto: 1) Viene assegnata alla variabile di istanza collStr il riferimento ad un nuovo Vector quindi no è mai null. 2) Il costruttore crea una collezione vuota che rappresenta la stringa vuota contenuta in ogni stringa, quindi qualsiasi sia il primo elemento va bene */ public Involucro(){ collStr = new Vector(); // Crea la collezione vuota assegnando a collStr il riferimento ad un nuovo Vector vuoto } /** Metodo inserisci() EFFECTS: Se il parametro può essere inserito nella collezione (se contiene completamente l'ultima stringa della collezione, allora viene inserito nella collezione rappresentata dall'oggetto ricevente, altrimenti viene sollevata una StringaNonValidaException MODIFIES: this @param: Un oggetto di tipo String Il metodo inserisci() soddisfa l'invariante di rappresentazione in quanto se la collezione è vuota permette l'inserimento di una stringa qualsiasi, se invece nella collezione è già presente qualcosa prima di inserire il parametro controlla che il parametro contiene completamente l'ultima stringa presente nella collezione. Se ciò è verificato la inserisce, altrimenti no e la collezione rimane sempre coerente con la sua definizione */ public void inserisci(String str){ int dimensione = collStr.size() ; // Contiene la dimensione del Vector collStr if(dimensione == 0) // Se la collezione è vuota collStr.addElement(str); // Aggiungi la stringa parametro in prima posizione else{ // Altrimenti, se nella collezione ci sono già degli elementi if(str.contains(collStr.elementAt(dimensione))) // Se i parametro contiene l'ultima stringa della collezione collStr.addElement(str); // Aggiungi la stringa parametro in prima posizione else throw new StringaNonValidaException(); // altrimenti solleva un'eccezione } } } Codice:
public class StringaNonValidaException extends RuntimeException{ public StringaNonValidaException(){ super(); } public StringaNonValidaException(String s){ super(s); } } C:\Programmi\Crimson Editor\template\esercizi\esami\11-07-07>javac Involucro.java Note: Involucro.java uses unchecked or unsafe operations. Note: Recompile with -Xlint:unchecked for details. A cosa si riferisce? Che problemi può creare? Soluzioni? Grazie Andrea Ultima modifica di e-commerce84 : 03-06-2009 alle 10:44. |
![]() |
![]() |
![]() |
#2 | |
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
Messaggio di warning presente da Java 5 in poi per via della presenza dei Generics; se nel codice si fa uso di collezioni senza lo specificatore di tipo il compilatore ricorda che, per l'appunto, non è in grado di controllare che la collezione sia usata in modo "type-safe".
Esempio di una collezione (List) di String usata in modo non type-safe: Codice:
// crea lista (di String?) List myList = new ArrayList(); // inserico un po' di String // bla bla... // ...più tardi // recupero (una String?) String maybe = (String) myList.get(0); Codice:
// crea lista [di String!] List<String> myList = new ArrayList<String>(); // inserico un po' di String // bla bla... // ...più tardi // recupero [una String!] String sure = myList.get(0); Codice:
for (String s : myList) { System.out.println(s); } In pratica usa in maniera trasparente un Iterator per recuperare un elemento per ciclo nella lista. Dimenticavo... Quote:
Semplicemente la tua collection resta una collection di Object e non di un tipo spefico; quando da codice ci infili dentro, che so, java.awt.Rectangle (per esempio) al momento della restituzione di un elemento la collection restituirà un Object: sei tu che lo devi sapere e che fai il cast a mano al giusto tipo. Il compilatore semplicemente non è in grado di controllare che tu stia facendo la "giusta" operazione di casting, e quindi ti stampa il warning per comunicartelo. Inoltre se in una collezione il cui tipo specifico è stato specificato, per esempio, come String, tu provi ad infilarci qualcosa di tipo non compatibile, il compilatore si arrabbia. Nella versione "non type-safe" semplicemente non c'è questo controllo, o meglio, dato che tutti gli oggetti in Java estendono implicitamente Object, il loro inserimento è sempre valido; vengono discriminati solo i tipi primitivi del linguaggio.
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) Ultima modifica di banryu79 : 03-06-2009 alle 12:02. |
|
![]() |
![]() |
![]() |
#3 |
Senior Member
Iscritto dal: Feb 2009
Messaggi: 700
|
mmm capisco...noi a lezione non abbiamo trattato i generics...ho capito di cosa si tratta e a cosa servono...appena ho un po' di tempo libero gli darò un'occhiata approfondita
![]() Questa è una parte di un compito d'esame...praticamente il testo diceva di progettare ed implementare questa classe Involucro che rappresenta collezioni di stringhe particolari come specificato nel primo post ed implementa le seguenti 3 operazioni: 1) Inserimento di una stringa in un oggetto di tipo Involucro (se possibile) con modifica dell'oggetto ricevente 2) Fusione di due oggetti <s1,s2,s3,...,sn> e <t1,t2,t3,...,tn> creando (se possibile) un nuovo oggetto di tipo Involucro: <s1,s2,s3,...,sn,t1,t2,t3,....tn> 3) Accesso in lettura alla collezione Io l'ho risolto così, dici che è una soluzione che va bene? (c'è tanta documentazione perchè la proff la vuole...maalla fine sono poche linee di codice) Codice:
/* La classe GestoreStringhe è un contenitore di metodi utili per operare sulle stringhe */ public class GestoreStringhe{ /* Metodo che prende due stringhe: nome e cognome; e che le unisce separandole con uno spazio e mettendo in maiuscolo le due iniziali ed in minuscolotutto il resto. Es: nome: "maRiO", cognome: "rOSsi" --> s = "Mario Rossi" */ public static String trasformaInUna(String nome, String cognome){ String s; s = nome.substring(0,1).toUpperCase(); s += nome.substring(1).toLowerCase(); s += " "; s += cognome.substring(0,1).toLowerCase()+cognome.substring(1).toLowerCase(); return s; } /* Metodo che permette di invertire la stringa che prende come parametro. Es: Se il metodo viene invocato con la stringa S="Roma", esso restituirà il riferimento all'oggetto di tipo String il cui valore è "amoR" */ public static String invertiStringa(String s){ String t; // Stringa da restituire che conterrà l'inversa della stringa s int i; // Variabile contatore t = null; // Inizializzazione: se s è vuota allora verrà restituita la stringa vuota /* Ciclo che copia in t i caratteri di s a partire dall'ultimo fino al primo */ for(i=s.length()-1; i>=0; i--){ // Per i che parte dalla lunghezza di s meno 1 fino ad aver letto tutti i caratteri t += s.substring(i,i+1); // Concatena a t l'i-esimo carattere di s } return t; } /* Metodo che permette di verificare se la stringa che prende come parametro è una stringa palindroma restituendo TRUE se è vero, FALSE al contrario. Es: S = "ama" --> restituisce TRUE, S = "ciao" --> restituisce FALSE */ public static boolean verificaPalindromia(String s){ String t; // Conterrà la stringa invertita t = invertiStringa(s); // Inverte la stringa s e la mette in t return s.equals(t); // Restituisce il risultato del test di uguaglianza tra s e t che può essere TRUE o FALSE } /* Metodo che permette di calcolare il prefisso comune delle due stringhe che prende come parametro */ public static String calcolaPrefissoComune(String s, String t){ int i, min; boolean trovato; // Diventa TRUE quando si trova un carattere diverso fra s e t String pref; if(s.length() < t.length()) min = s.length(); else min = t.length(); trovato = false; // Inizializzazione della variabile trovato a false poichè non è ancora stato trovato un carattere diverso fra s e t pref = ""; // Inizializzazione delle string pref con la stringa vuota, il prefisso comune è inizialmente nullo i = 0; // Inizializzazione il contatore a 0 while((i<min) && (!trovato)){ // Finchè il contatore è minore del possibile prefisso e non è stato ancora trovato un carattere diverso fra s e t if(s.substring(i,i+1).equals(t.substring(i,i+1))){ // Se l'i-esimo carattere delle 2 stringhe è uguale pref += s.substring(i,i+1); // Concatena a pref l'i-esimo carattere comune alle 2 stringhe i++; // Incrementa di uno il contatore per andare a testare il prossimo carattere } else trovato = true; // Altrimenti impostra trovato a true } return pref; // Restituisci il prefisso comune trovato } } |
![]() |
![]() |
![]() |
#4 |
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
alcune osservazioni
Riporto solo il codice, senza i commenti.
Classe Involucro Codice:
import java.util.*; public class Involucro{ Vector collStr; // Rappresenta la collezione di stringhe public Involucro(){ collStr = new Vector(); } public void inserisci(String str){ int dimensione = collStr.size() ; if(dimensione == 0) collStr.addElement(str); else{ if(str.contains(collStr.elementAt(dimensione))) // [1] collStr.addElement(str); else throw new StringaNonValidaException(); // [2] } } } Se hai già inserito la prima String nel Vector e stai inserendo la seconda, per esempio, il metodo size restituirà 1, valore che viene copiato in 'dimensione'. Quindi fare: "collStr.elementAt(dimensione)" significa fare "collStr.elementAt(1)" che punta al secondo elemento nel Vector (il primo, quello effettivamente inserito, è 0) ma siccome il secondo elemento ancora non esiste avrai un tentativo di accesso ad un indice non valido a runtime percui dopo aver inserito la prima String nel Vector le successive chiamate al metodo 'inserisci' lancieranno una ArrayIndexOutOfBoundsException. Questo è un'errore di programmazione, prova a correggerlo. [2] L'eccezione definita da te per segnalare il caso in cui la String passata al metodo non è un argomento valido ricalca il significato di un'ecezione già presente nel JDK e che puoi usare: la IllegalArgumentException (ed è una RuntimeException). La trovi nel package java.lang, il package importato di default, quindi è già disponibile. Citando javadoc circa IllegalArgumentException, dice: "Thrown to indicate that a method has been passed an illegal or inappropriate argument.". Il che ricalca esattamente il motivo d'essere della tua eccezione. Per GestoreStringhe: Codice:
public static String trasformaInUna(String nome, String cognome){ String s; s = nome.substring(0,1).toUpperCase(); s += nome.substring(1).toLowerCase(); s += " "; s += cognome.substring(0,1).toLowerCase()+cognome.substring(1).toLowerCase(); return s; }
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) |
![]() |
![]() |
![]() |
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 12:19.