2013-01-15 19 views
10

Ho provato a creare una classe personalizzata String nel pacchetto java.lang nel mio spazio di lavoro di eclissi. Inizialmente ho il sospetto che una stessa classe in uno stesso imballaggio non può essere creato, ma con mia grande sorpresa sono stato in grado di creare una classe (String) nella stessa confezione cioè java.langCreazione di una classe String personalizzata

Ora sono confuso
1) perché è possibile e
2) quale può essere la ragione se è permesso.
3) quale sarà l'uso se questo tipo di creazione di classi java è consentito in Java.

+0

Se la memoria non serve, il pacchetto 'java.lang' è [sigillata] (http://docs.oracle.com/javase/6/docs/technotes/ guide/extensions/spec.html # sealing) quindi non è possibile aggiungere membri ad esso. Sarei sorpreso se la sostituzione del tipo 'String' senza farlo nel vaso di runtime sarebbe successo dato quanto sia fondamentale il tipo per il funzionamento della JVM. – McDowell

risposta

9

È possibile creare una nuova classe nel pacchetto java.lang. Se fosse vietato in che modo gli sviluppatori Oracle sarebbero in grado di sviluppare Java? Sono sicuro che usano lo stesso javac di noi.

Ma non sarà possibile caricarlo, perché java.lang.ClassLoader (che qualsiasi programma di caricamento classe estende) non lo permette, ogni classe di essere caricati passa attraverso questo controllo

... 
     if ((name != null) && name.startsWith("java.")) { 
      throw new SecurityException 
       ("Prohibited package name: " + name.substring(0, name.lastIndexOf('.'))); 
     } 
... 

in modo da finire in qualcosa di simile

Exception in thread "main" java.lang.SecurityException: Prohibited package name: java.lang 
    at java.lang.ClassLoader.preDefineClass(ClassLoader.java:649) 
    at java.lang.ClassLoader.defineClass(ClassLoader.java:785) 
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) 
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:449) 
    at java.net.URLClassLoader.access$100(URLClassLoader.java:71) 
    at java.net.URLClassLoader$1.run(URLClassLoader.java:361) 
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354) 
    at java.lang.ClassLoader.loadClass(ClassLoader.java:423) 
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308) 
    at java.lang.ClassLoader.loadClass(ClassLoader.java:356) 
    at Test1.main(Test1.java:11) 

Per quanto riguarda le classi che ombra classi esistenti come il tuo java.lang.String non può essere caricato perché il System Class Loader (quello di default) usa la strategia "genitore prima", quindi le classi java.lang verranno caricate da rt.jar con bootloader. Quindi dovrai sostituire String.class in rt.jar con la tua versione. Oppure sostituirlo con utilizzando l'opzione java -Xbootclasspath/p: che antepone i percorsi ai percorsi di ricerca del caricatore di classe bootstrap. Così si può

1) copypaste contenuto reale String.java nella vostra String.java

2) cambiare un metodo, ad esempio

public static String valueOf(double d) { 
    return "Hi"; 
} 

e compilare lo String.java

3) creare una classe di test

public class Test1 { 

    public static void main(String[] args) throws Exception { 
     System.out.println(String.valueOf(1.0d)); 
    } 
} 

4) eseguirlo come

012.351.641,061 mila
java -Xbootclasspath/p:path_to_your_classes Test1 

e vedrete

Hi 
+1

Come risponde questa risposta alle 3 domande poste dall'OP? – SpaceTrucker

2

Sì, è possibile creare il pacchetto con il nome java.lang e anche classe denominata come String.

Ma non sarai in grado di eseguire la tua classe String.

1) perché è possibile: Il compilatore compilerà correttamente la classe.

2) quale può essere il motivo se è consentito: Si ha un nome valido per il pacchetto e la classe, quindi il compilatore non si lamenta.

3) quale sarà l'uso se questo tipo di creazione di classi java è consentito in Java: Ma non c'è molto uso di questa classe String. Il caricatore di classe Bootstrap carica la classe dal pacchetto java.lang di sun. Quindi la tua classe String personalizzata non verrà caricata e quindi fallirà durante l'esecuzione.

Il caricatore di classe Bootstrap fa parte dell'implementazione JVM e carica le classi dell'API Java (che include java.lang.String). Inoltre, per ogni classe che viene caricata, JVM tiene traccia di quale caricatore di classi, bootstrap o definito dall'utente, ha caricato la classe. Quindi qualsiasi tentativo di caricare una classe String personalizzata avrà esito negativo poiché la classe String è già stata caricata.

+0

Dovresti spiegare perché non sarà in grado di eseguire. – SpaceTrucker

+0

penso di aver spiegato ... –

+0

grazie rai.sKumar, se avessi avuto due scelte per la selezione delle risposte, avrei sicuramente scelto questa come seconda migliore risposta. Perché era chiaro, preciso e al punto Risposta. Ma la risposta selezionata da Evgeniy Dorofeev è tale che (anche il codice) anche un laico può capire e simulare il problema, quindi tenetelo a mente, ho scelto la sua risposta come risposta accettata, ma comunque molto molto spesso :) –

4

Questo è chiamato classe shadowing.

1.) È possibile perché le classi java non sono collegate staticamente, ma collegate al tempo di caricamento della classe.

2.) Se non fosse consentito, l'intero caricamento della classe sarebbe molto più difficile da raggiungere. Quindi, ad esempio, dovresti anche costruire il tuo progetto su una versione Java specifica. perché le classi Java possono cambiare da versione a versione. Questo non sarà un approccio sostenibile.

3.) osgi si avvale di questo per poter caricare diverse versioni dello stesso pacchetto. Un altro caso d'uso comune è quello di sostituire le classi buggy nei framework, dove non è possibile nessun altro workaround. Tuttavia questa tecnica dovrebbe essere utilizzata con attenzione, perché gli errori potrebbero essere difficili da eseguire il debug.

Si noti che tuttavia le classi di shadowing nei pacchetti java. * Non sono consentite, in quanto ciò interromperà la sandbox di sicurezza Java. Quindi avrai problemi a runtime.

Problemi correlati