2013-08-08 9 views
6

Sto provando a giocare con la riflessione per vedere se riesco ad arrivare a un punto in cui sono in grado di digitare un nome di classe e la mia applicazione caricherà quella classe e ne creerà un'istanza. Dopo alcuni tentativi ho scoperto che non potevo semplicemente inserire un nome di classe in Class.forName() senza il nome del pacchetto, quindi ho finito col cercare di ottenere un elenco di tutti i pacchetti disponibili che sono stati caricati e cercando di caricare la classe I con ogni nome del pacchetto fino a quando non ottiene un successo.Perché il mio riflesso carica strane lezioni?

Questo è quello che ho finora:

BufferedReader console = new BufferedReader(new InputStreamReader(System.in)); 
    String s = ""; 
    do 
    { 
     ClassLoader clsldr = ClassLoader.getSystemClassLoader(); 
     Package[] pkgs = Package.getPackages(); 
     s = console.readLine(); 
     if(s.equals(":exit")) 
     { 
      System.exit(0); 
     } 
     boolean classFound = false; 
     Object loadedClass = null; 
     String classname = ""; 
     for (int i = 0; i < pkgs.length; i++) { 
      Package package1 = pkgs[i]; 
      try 
      { 
       classname = package1.getName().replace('/', '.') + "." + s; 
       clsldr.loadClass(classname); 
       loadedClass = Class.forName(classname); 
       classFound = true; 
      } 
      catch(Exception e) 
      { 

      } 

     } 
     System.out.println("LOADED A CLASS!!!!"); 
     System.out.println(classname); 
     System.out.println(loadedClass); 
    } 
    while(s.length() == 0); 

Funziona semi in un modo molto strano. Ad esempio, quando digito "Oggetto" al prompt, in qualche modo riesce a caricare sun.net.util.Object, ma quando stampo l'oggetto reale viene stampato class java.lang.Object. Ottengo la stessa cosa con un String e molte altre cose che ho digitato. Una cosa interessante che ho provato è stata int - ha caricato sun.net.util.int e quando ho stampato l'oggetto ha appena restituito null. Un altro successo quando ho provato Java:

Java 
LOADED A CLASS!!!! 
sun.net.util.Java 
null 

Qualcuno ha qualche idea di cosa sta succedendo qui? C'è qualcosa di speciale nel pacchetto sun.net.util che sta causando questo? Non mi interessa davvero che il mio codice non funzioni esattamente come voglio, mi piacerebbe solo sapere cosa sta causando questo strano comportamento.

versione Java:

java version "1.7.0_25"           
Java(TM) SE Runtime Environment (build 1.7.0_25-b17)    
Java HotSpot(TM) 64-Bit Server VM (build 23.25-b01, mixed mode) 

Sono su Windows 8 a 64 bit se che fa alcuna differenza.

risposta

0

Ho solo pensato a qualcosa: non ho mai interrotto il mio giro quando ho seguito una lezione. Quindi questa cosa sta probabilmente arrivando a java.lang.Object che imposta la classe caricata su true, ma continua nel ciclo che sovrascrive la classe effettiva che è stata caricata, e sun.net.util è probabilmente l'ultimo pacchetto caricato sul mio sistema. Tutto ciò di cui ho bisogno è una dichiarazione di rottura e dovrebbe fermare questo comportamento.

+0

Tranne che lo schema fallirà se la classe "strana" è quella che appare per prima. O se nessuna delle due classi è "strana"; per esempio. 'java.util.Date' versus' java.sql.Date'. –

0

Le classi che iniziano con sun e com.sun sono classi interne e in gran parte non documentate "domestiche" utilizzate dagli interni di JVM. Non fanno parte dell'API Java e diverse JVM ne avranno di diverse. Il fatto che tu stia vedendo tutti questi interni diversi è il motivo per cui devi specificare un nome completo per l'API di Reflection. ;-)

+0

Ho pensato che ... pensi che sarebbe opportuno ignorare i pacchetti 'sun. *' E 'com.sun. *' Per evitare questo comportamento? C'è un modo migliore per fare una ricerca di classe/pacchetto? – Logan

+0

Per quale scopo? Solo per la sperimentazione? E non è possibile ignorare completamente 'com.sun', dal momento che alcune di queste classi sono regolarmente visibili nel normale funzionamento, in genere dietro le interfacce (implementazioni di algoritmi crittografici selezionati da una chiave di ricerca' String', ad esempio). Le librerie SCTP, IIRC, sono anche in 'com.sun' e usate direttamente. – chrylis

+0

Sì, praticamente. Volevo provare a realizzare un interprete Java: D – Logan

3

Il codice restituisce classi "strane" perché ciò che sta facendo è concettualmente interrotto. Non c'è nulla in alcuna specifica che dice quale dovrebbe essere l'ordine fisico delle voci nel file "rt.jar". Sono semplicemente in un ordine che ti porta a trovare quello "strano" dato il modo in cui stai facendo l'iterazione. In un'altra versione Java, il tuo codice potrebbe darti la classe "non strana" Object. In ogni caso, il presupposto che otterrete la "giusta" classe in questo modo è ... imperfetto.


Tu dici che si sta facendo questo perché:

"Ho voluto prendere una pugnalata a fare un interprete Java"

Beh, se avete intenzione di implementare un interprete, devi capire il linguaggio Java. E una delle cose che devi capire è che ci possono essere molte classi con lo stesso nome semplice in Java. Ciò significa che la tua idea di scansionare il classpath per qualsiasi classe con un nome semplice dato non è semplicemente pratica. Scoprirai che ci sono troppe "collisioni" (cioè classi con lo stesso nome semplice) per le classi di uso comune.

In Java convenzionale, questo problema di collisione viene risolto facendo riferimento alle classi con i nomi completi o tramite importando. Affinché l'interprete sia utilizzabile, è necessario implementare uno schema di importazione che rispecchi il meccanismo di importazione convenzionale di Java.

In breve, metti il ​​codice sopra e ricomincia.

+0

Stavo aspettando questa risposta :) come ho detto, questo pezzetto di codice era solo per la sperimentazione, ho poca esperienza con il riflesso, quindi volevo solo bagnarmi i piedi. Inoltre, la mia domanda era "perché questo codice carica classi strane" e non "come posso aggiustarlo". Grazie per il suggerimento, probabilmente tornerò a chiedere aiuto con lo schema di importazione :) – Logan

+0

Ho indirizzato la parte "perché" della tua domanda. (Non l'ho fatto prima perché pensavo fosse ridondante, ma dal momento che insisti ...) –

Problemi correlati