|
View Content
Hide Content
Qualcuno mi sa spiegare bene il comportamento della "System.gc()" ?
Vi prego di rispondere al più presto. Grazie a tutti
|
|
View Content
Hide Content
Ho la necessità di implementare un ascoltatore per la terminazione di un thread. Cercando nelle API non ho trovato nulla di attinente al mio problema. Consigli?
|
|
View Content
Hide Content
Argomento fuori programma (lo dico per chi si potrebbe spaventare..). Come vedrete in Sistemi operativi, la terminazione di una thread è una operazione delicata. Esistono i metodi stop e destroy di thread, che sono deprecati. Nella documentazione di Thread c'e' scritto il perchè. Tuttavia se non si usano delle variabili condivise protette da monitor non dovrebbero esserci problemi particolari e si può usare stop. Naturalmente bisgna farsi passare l'identificatore della Thread su cui eseguire lo stop.
| |
|
View Content
Hide Content
Supponiamo di avere un codice nel quale viene usata una assert. Per esempio, prendiamo questo programmino, peraltro già discusso nel forum:
class DemoAssert {
int x = 5; public void stampaInteroPositivo(int i) { assert i >= 0:stampaErroreAssert(); System.out.println(i); }
public int stampaErroreAssert() { System.out.println("XX"); return -1; }
public static void main(String args[]) { int x = -10; DemoAssert test = new DemoAssert(); test.stampaInteroPositivo(x); } }
L'output prodotto è il seguente:
Exception in thread "main" java.lang.AssertionError: -1 at DemoAssert.stampaInteroPositivo(DemoAssert.java:5) at DemoAssert.main(DemoAssert.java:17) XX
Dato che l'eccezione AssertionError non è stata inserita in un try...catch, provocando di conseguenza la terminazione del programma, devo considerare il comportamento del programma un "runtime error alla riga 5" oppure devo dire che "il codice esegue correttamente e l'output è: XX"? In fin dei conti, entrambe le risposte sono due mezze verità... o no?
|
|
|
View Content
Hide Content
E' possibile evitare il Dynamic Binding e, in riferimento al file in attachment, chiamare il metodo f della classe parent?
|
|
View Content
Hide Content
Penso di si, correggetemi se sbaglio:
Potresti dichiarare final il metodo f della classe madre.
class A { final void f(int n) { System.out.println("Class A: " + n * 2); } }
Tristemente questo implica che tutte le classi figlie non potranno fare l'overriding del metodo... ma puoi sempre usare la scappatoia dell'overloading, per esempio aggiungendo un dato inutilizzato.
Ok, la soluzione non e' molto pulita, ma dovrebbe funzionare...
|
|
View Content
Hide Content
Non è esattamente quello che vorrebbe Ivan. Lui vorrrebbe poter dire al sistema che nonostance che esistano metodi f in A e in B, si desidera nel contesto specificato dal suo codice che ( (A) a).f(1); esegua il metodo f di A e non di B. No, non si può fare. In C++ il linguaggio permette di scegliere se si vuole binding statico o dinamico, in Java è dinamico. Quello che propone lei è di VIETARE di sovrascrivere il metodo f nelle classi figlie di A. Certo, così tutte richiamano il metodo f di A, ma non è una risposta alla domanda di Ivan.
| |
|
|
View Content
Hide Content
Quando sono stati spiegati a lezione upcast e downcast ero assente e ho notato che purtoppo nel video in cui sarebbero dovute essere presenti manca proprio quella parte -_-
Guardando le slide e cercando anche sul web ho trovato delle discrepanze. Ad esempio nelle slide non capisco come mai viene indicato come upcast implicito corretto il fatto che l'istanza a della classe A chiami il metodo f1(), che è proprio di A! Non dovrebbe essere invece b.f1() ad essere un upcast implicito corretto, essendo B sottoclasse di A?
Inoltre ho provato a copiare il codice delle slide in JBuilder, per cercare di capire la differenza a livello di compilazione e a runtime, ma ho visto che mi segnala errore il compilatore anche in righe che sulle slide sono marcate come corrette... Ad esempio per chiamare il metodo f2() di B (che è sottoclasse di A) viene eseguita la riga ((B)a).f2() che dovrebbe essere corretta in quanto f2() è un metodo di B, e quindi per chiamarlo su A effettuo un downcast da A a B. Non capisco come mai JBuilder me lo segnali come errore, dicendomi "inconvertible types".
Per ultimo ho visto che il compilatore mi segnala errore anche in upcast ovvi, ad es, sempre prendendo le classi delle slide:
a=(A)b;
mi dà inconvertible types, nonostante B sia sottoclasse di A e quindi l'upcast dovrebbe essere corretto. Mentre invece facendo public class Insetto {...} e public class Grillo extends Insetto {...} e poi Grillo g=new Grillo(); e Insetto i=(Insetto)g; funziona, nonostante sia uguale all'esempio di A e B! Sono un po' confuso...
|
|
View Content
Hide Content
Prima domanda: nella prima slide di pagina 8 della lezione 13 (lei si riferisce a quella) La variabile a è di tipo A ma nella sua pancia di a c'e' una istanza di tipo B. Al momento dell'esecuzione sull'istanza (di tipo B) viene fatto un upcast implicito perchè essa è trattata come una variabile di tipo A.
Secondo punto: la scrittura ((B)a).f2(1); è corretta, ed in JBuilder risulta corretta. Attenzione però che se prima scrivete a.f2(1) ; ed eseguite, vi rimane in basso segnato l'errore compiuto precedentemente anche quando correggete la riga. RIcompilando la segnalazione di errore (che è vecchia e risale al giro prima) scompare. Il permanere della vecchia segnalazione può confondere. Idem per quanto riguarda l'ultimo punto, ovvero il presunto errore su a=(A)b;. L'errore non c'e'. Ricompili e vedrà che la vecchia segnalazione sparisce. E' solo un problema di interpretazione dei messaggi che arrivano da Jbuilder.
| |
|
View Content
Hide Content
Stavo provando un po' di esercizi della parte teorica per capire meglio il funzionamento del garbage collector. Prendo in causa l'esercizio che richiama due volte il garbage collector.
package uno; public class A { C c=null; public A() { System.out.print("+10"); C c1=new C(); c=new C(); } public static void main(String[] args) { A a = new A(); System.gc(); new C(); a = null; System.gc(); } } class C { static int count=0; String name=null; public C() { name="2"+(++count); System.out.print("+"+name); } protected void finalize() { System.out.print("-"+name); } }
L'output corretto segnalato dal professore è +10+21+22-21+23-22-23. Provando l'esercizio con jbuilder ho notato che l'output cambia ogni volta (a parte per i primi output ovvero +10+21+22). Ad esempio mi è capitato come output +10+21+22-21+23-23-22 oppure +10+21+22+23-21-22-23. Perchè accade questa cosa? Il garbage collector è un thread indipendente e quindi può eseguire la pulizia in ritardo rispetto a quando l'ho richiesto? Nel caso di domande simili all'esame, come dobbiamo comportarci? Grazie
|
|
View Content
Hide Content
Gli ultimi due dati vengono stampati dalla finalize nell'ultima chiamata al gc. L'ordine con cui vengono stampati dipende da come erano stati allocati in memoria e da come il gc ispeziona la memoria, quindi può esserci una inversione dei due valori.
L'inversione tra +23 e -21 è più rara e dipende come lei suppone dal fatto che la gc gira in una thread separata, quindi l'ordine con cui le due thread effettuano le rispettive azioni non è deterministico.
Le soluzioni corrette sono tutte quelle che si possono verificare. Ai fini del compito è sufficiente dare una delle soluzioni possibili. Per semplicità, in generale suggerisco di considerare il codice come se la gc fosse completamente eseguita dal comando gc(), e quindi senza considerare il multithreading, e di distruggere le variabili nell'ordine con il quale sono state costruite. Con questa procedura si identifica una delle possibili soluzioni corrette (quella indicata come output nel testo).
| |
|
View Content
Hide Content
Cosa s'intende per "Stringa Regolare" e come variano le procedure di equaglianza tra di loro?
ps Questo problema l'ho riscontrato spesso in PHP e voelvo sapere se Java avesse un comportamento del genere.....
|
|
|
View Content
Hide Content
Scusate la domanda banale...
In un programma da me fatto non riesco a fare una semplice radice quadrata..mi da errore perchè dice che non trova il metodo sqrt nel mio package..
Io però ho importato la libreria java.math e ho provato anche con java.lang ma non va...Attendo vostra risposta. Grazie
|
|
View Content
Hide Content
Basta guardare le API, o cercare con google "java sqrt". Occorre poi ricordare cosa significa "static" e si risolve il problema.
| |
|
View Content
Hide Content
E' possibile conoscere a runtime se un oggetto implementa una certa interfaccia?
|
|
View Content
Hide Content
Certo. La cosa più semplice è usare l'operatore instanceof: myobject instanceof MyClass oppure myobject instanceof MyInterface ritorna true se myobject è istanza di una (sotto)classe di MyClass o di una classe che implementa MyInterface o se uno degli antenati di MyClass implementano MyInterface.
Si può anche usare il metodo isInterface della classe Class (si vedano le relative API: http://sunsite.tus.ac.jp/java/JDK1.1/docs/api/java.lang.Class.html
| |
|
View Content
Hide Content
Parlando di applet, a lezione, è stato posto in rilievo il problema sicurezza. In particolare si è detto che:
- Le applet non possono accedere ai filesystem locali;
- Non è possibile aprire connessioni se non verso il server di provenienza della pagina web.
Si supponga che un host disponga dei seguenti servizi:
- Webserver (che serve la pagina html contenente l'applet) su porta 80
- Server secondario (che fornisce un servizio generico all'applet) su porta x
L'utente che si connette al sito web (porta 80) ottiene la possibilità di utilizzare l'applet che, a sua volta, si connette al server secondario (porta x).
Domanda: Un proxy interposto tra client e server vede tale operazione come un traffico http o come due traffici separati? In altre parole: viene eseguita una qualche sorta di tunneling http, o la trasmissione è indipendente?
|
|
|
View Content
Hide Content
Ciao a tutti, innanzitutto segnalo al webmaster, cioè al nostro professore, che il post:
Re: Test d'esame by Marco Ronchetti on 5/9/2006 10:28 PM
ha causato una cattiva impaginazione, allungando eccessivamente la pagina in orizzontale.
A parte ciò, avrei bisogno di capire meglio la differenza concettuale e sintattica tra classe privata e inner class. Vi scrivo quello che credo di aver capito, dopo aver fatto alcune prove con JBuilder. Correggetemi se sbaglio...
1. Inserendo una classe all'interno delle parentesi graffe di un'altra, ottengo una inner class, istanziabile esclusivamente dalla classe che la racchiude, indipendentemente dai modificatori di visibilità specificati (dei quali, in questo caso, non comprendo quindi l'utilità). 2. Una inner class può essere resa anonima, racchiudendone tra graffe, posizionate all'interno della lista di argomenti di un metodo della classe ospitante, le variabili di istanza e i metodi: in questo caso non è possibile specificare modificatori di visibilità. 3. Posso scrivere una o più classi all'interno dello stesso file ed esternamente alle parentesi graffe della classe public: non posso specificare modificatori di visibilità, però queste classi saranno istanziabili da qualunque altra classe contenuta nel medesimo package.
Cosa ne pensate?
|
|
View Content
Hide Content
1. i modificatori di visibilità sono specificabili quando si definisce una inner class non anonima e sono effettivi (pensa al caso di una inner class private che non è visibile in una sottoclasse della outer class mentre lo è se definita protected o public).
2. in questo caso i modificatori di visibilita non si specificano perché da nessuna parte del codice è possibile tentare di accedervi (la classe non ha un nome) Esistono oggetti di quella classe (nei nostri esempi di solito uno), ma non posso fare undowncast esplicito dell'oggetto al tipo classe anonima per richiamare eventuali metodi definiti solo nella classe anonima. I metodi ereditati invece hanno la visibilità specificata nell'interfaccia o nella superclasse.
3. le classi per cui non è specificato un modificatore di visibilità hanno visibilità di package
| |
|
View Content
Hide Content
Ho provato ad eseguire il seguente codice ed il suo comportamento mi ha lasciato alquanto perplesso.
class DemoAssert { int x=5; public void stampaInteroPositivo(int i) { assert i >= 0 : stampaErroreAssert(); System.out.println(i); } public int stampaErroreAssert() { System.out.println("XX"); return -1; } public static void main(String args[]) { int x=-10; DemoAssert test = new DemoAssert(); test.stampaInteroPositivo(x); } }
Sembrerebbe che l'assert non venga mai eseguita ne con x positivi ne negativi. Ho anche usato il programma di debug e anche se x ha valore negativo l'assert non viene eseguita. Qual'è la soluzione? Perché? Qual'è il modo corretto di usare l'assert in questo esempio?
|
|
View Content
Hide Content
Sicuro? Io ho provato il codice (cut & paste da qui sopra) e l'output che ottengo è:
C:binJBuilderXjdk1.4binjavaw -classpath "...;C:binJBuilderXjdk1.4libtools.jar" untitled1.DemoAssert -ea java.lang.Error: -1
at untitled1.DemoAssert.stampaInteroPositivo(DemoAssert.java:5)
at untitled1.DemoAssert.main(DemoAssert.java:15)
XX
Exception in thread "main"
Naturalmente per poterlo compilare ho dovuto abilitare le asserzioni, ma senza farlo il compilatore dà (giustamente) errore. Ho usato JBuilderX sotto WinXP , ma il risultato non dovrebbe dipendere da questo.
| |
|
View Content
Hide Content
Ciao, non riesco a capire come mai l'output di questo sorgente mi dia ACBDFEFE L' output comincia con AC, poichè viene istanziato un oggetto di classe B che è un estensione della classe A (il supercostruttore è il costruttore di A(), il costruttore è quello di B() ) Non riesco a comprendere il seguito. Qualcuno saprebbe aiutarmi? Grazie
#include <iostream.h> class A { public: A() {cout<<"A";}; A(A &a) {cout<<"B";} ~A() {cout<<"E";} }; class B:public A { public: B() {cout<<"C";}; B(B &a):A(a) {cout<<"D";}; ~B() {cout<<"F";}; } ; int main() { B * b = new B(); B c=*b; delete b; }
|
|
View Content
Hide Content
E' fuori dal programma di quest'anno. Richiede di sapere cosa sia e come funziona un copy constructor in C++ [nel codice è il metodo A(A &a) ] e come i copy constructors si invochino a catena [ B(B &a):A(a) ]. Per chi dovesse essere interessato all'argomento che, ripeto, non è nel programma di quest'anno, suggerisco la lettura di "Thinking in C++" di Bruce Eckel.
| |
|
View Content
Hide Content
Non riesco a compilare il file in attachment; non riconosce la keyword assert.
|
|
View Content
Hide Content
Dopo un po' di tentativi sono riuscito a compilare ed eseguire:
- compilazione: javac -source 1.4 AssertTest.java
- esecuzione: java -ea AssertTest
Ovviamente il codice genera appositamente un errore.
| |
View Content
Hide Content
Per compilare con la assert, occorre aggiungere lo switch "-ea" sulla riga di comando di javac.
Da JBuilder occorre scegliere il menu "Project -> Project Properties", nel pannello scegliere Build -> Java e da li' settare "Enable assert keyword".
| |
|
View Content
Hide Content
Vorrei inserire il post in "Basi di Java e OOP", però non mi è possibile, perché, secondo quanto riportato nella relativa pagina, "only specified groups or individuals can participant"...
Come da oggetto, la mia domanda riguarda le variabili statiche, in riferimento ad un esempio presentato a lezione e qui allegato. L'output è: # of instances:10 # of instances:0
Facendo un decremento di instanceCount in finalize(), il suo valore passa da 10 a 0, facendo invece un incremento, passa da 10 a 20... Perché accade questo?
|
|
View Content
Hide Content
Semplicemente perchè chiamo per 10 volte un incremento in fase di creazione delle istanze, e altre 10 volte incremento quando distruggo le istanze... Non sto accedendo al contatore di istanze interno di Java, ma una MIA variabile con la quale faccio quello che voglio. Se moltiplicassi per 2 invece di incrementare, otterrei 10240...
Per i problemi di accesso a "Basi di Java e OOP" non capisco, ci deve essere qualche settaggio che mi sfugge, proverò a sistemarlo.
| |
|
View Content
Hide Content
Ho una domanda per quanto riguarda l'esecuzione dei file .class. Fino ad ora l'esecuzione dei programmi java da me creati l'ho sempre effetuata con Jbuilder, ma quando devo portare i file su un altra macchina (La macchina ha OS Windosw e JDK Installato non ho ovviamente jBuilder che è scomodo e lascia la possibilità di modificare il codice.....) ho dei problemi nell'esecuzione da propmt dei comandi. La documentazione dice che basta la riga di comando: "Java nomefile" sottointendendo che in file sia compilato e che al suo interno abbia un main eseguibile. Purtroppo mi continuo a ritrovare questo errore: "Exception in thread "main" java.lang.NoClassDefFoundError: Esercizio2" ma il main nella calsse esiste e funziona (testato con Jbuilder). Come posso fare? Lo scopo di questo è quello di riuscire ad ottenere è un file .bat che con un semplice clic lancia l'esecuzione del programma....
|
|
View Content
Hide Content
Occorre sempre che il sistema operativo trovi il comando "java": questo si ottiene settando la variabile di ambiente PATH in modo da includere la directory bin della distribuzione del JDK (in Windows pannello di controllo System - Advanced - Environment variables), e non è il suo problema. Occorre poi che la JVM trovi le librerie giuste, e questo si ottiene settando la variabile di ambiente CLASSPATH, in modo da includere la directory lib del JDK.
Per capire bene come funzionano le cose, suggerisco de leggere la DOCUMENTAZIONE sul sito della Sun
| |
|
View Content
Hide Content
Due domande per la stesura di codice "pulito e leggibile" in Java:
- Esistono delle convenzioni (diffuse o meno tra gli sviluppatori Java) per assegnare dei nomi intuitivi alle classi Listener associate ai vari oggetti?
- Vari oggetti grafici che necessitano di Listeners, richiedono di stabilire una politica di implementazione efficace degli ascoltatori. Illustro due casi estremi:
- genero un ascoltatore unico per tutti gli oggetti che devono essere "ascoltati" al click del mouse, e di conseguenza sarà l'ascoltatore a riconoscere l'oggetto che ha generato l'evento (complessità dell'ascoltatore)
- genero un ascoltatore per ogni ogetto (proliferazione di oggetti ascoltatori)
Quale è la soluzione migliore che pondera tra efficienza e semplicità?
|
|
View Content
Hide Content
Vedremo in seguito che spesso i Listener sono creati con delle "classi interne anonime": per queste il problema del nome non si pone, ma le discuteremo a lezione più avanti.
Non mi pare che ci siano politiche standard per la definizione dei nomi dei listeners. In genere direi che vale il principio generale: il codice va scritto in modo da poter essere letto e compreso. Quindi una strategia potrebbe essere quella di dare al Listener un nome significativo (in uno degli esempi fatti in classe il listener si chiamava Painter, perchè secondo me così si rendeva intuitivo il ruolo di quella classe.
Riguardo alla seconda domanda, in effetti scrivere un listeners ad hoc per ogni generatore di eventi (che è quello che fanno gli IDE dotati di visual editor, come il generatore di intefacce di JBuilder) provoca una proliferazione di classi. Per questo le classi interne (anonime o meno) possono essere utili. D'altra parte, concentrare in un unico listener il controllo di tanti oggetti implica che nel suo codice occorra fare una "getSource()" sull'evento passato per sapere chi lo ha generato, e sulla base di questa informazione decidere l'azione da compiersi. A volte questa scelta può essere conveniente. Tale scelta (concentrare il controllo in una singola componente) si avvicina ad un pattern codificato e molto usato, il Model-View-Controller nel quale il Model gestisce i dati, il View si occupa di farne la presentazione (grafica o meno) e il controller gestisce la logica degli eventi. In tal caso il controller potrebbe agire da listener per tutti gli eventi generati.
Non esiste però un ricetta generale: a volte è preferibile la prima soluzione e a volte la seconda.
| |