2016-04-20 7 views
7

Dato un nome classe completo che può può essere caricato con Class.forName(), c'è un modo per trasformare il nome in quello che sarebbe il risultato del caricamento della classe e invocando getSimpleName() senza effettivamente tentare di caricare il classe? Ho bisogno di questa capacità per scopi di riflessione.Qual è il modo migliore per approssimare class.getSimpleName() senza caricare la classe?

+1

Suppongo che si debba implementare la logica da soli: si tratta principalmente dell'ottenere l'ultimo elemento in una stringa ''. Separata '; con alcune campane e fischietti ... –

+0

@BoristheSpider e la stringa potrebbero anche contenere un '$' – wero

+0

@wero yup, "campane e fischietti" - se è '\ $ \ d + $' quindi 'null', altrimenti diviso in' $ '. –

risposta

4

Devo dire che non è possibile farlo semplicemente in base al nome.

Si può cercare di dividere il . e $, ma questo codice di esempio dimostra che non è sempre ovvio dove inizia il semplice nome:

class Ideone 
{ 
    private static class Bar {}; 

    public static void main (String[] args) throws java.lang.Exception 
    { 
     class Foo$o { 
     class Bar$bar {} 
     }; 
     class Foo$o$Bar { 
     class Bar$bar {} 
     }; 
     class Foo$o$Bar$Bar$bar {} 
     print(Ideone.class); 
     print(Bar.class); 
     print(Foo$o.class); 
     print(Foo$o.Bar$bar.class); 
     print(Foo$o$Bar.Bar$bar.class); 
     print(Foo$o$Bar$Bar$bar.class); 
    } 

    private static void print(Class<?> clazz) { 
     System.out.printf("fqn=%s, sn=%s%n", clazz.getName(), clazz.getSimpleName()); 
    } 
} 

uscita:

fqn=Ideone, sn=Ideone 
fqn=Ideone$Bar, sn=Bar 
fqn=Ideone$1Foo$o, sn=Foo$o 
fqn=Ideone$1Foo$o$Bar$bar, sn=Bar$bar 
fqn=Ideone$1Foo$o$Bar$Bar$bar, sn=Bar$bar 
fqn=Ideone$2Foo$o$Bar$Bar$bar, sn=Foo$o$Bar$Bar$bar 

Ideone demo

ie se dovessi dire "il bit del nome dopo l'ultimo $ o . ", ti sbaglieresti.

L'unico modo conclusivo per fare questo è quello di caricare la classe, potenzialmente senza inizializzarla:

Class<?> clazz = Class.forName(className, false, someClassLoadeR); 
+0

Oppure vieni con un set completo di casi - come hai dimostrato non ce ne sono molti - e implementalo. Il test unitario sarebbe ben banale. –

+1

@BoristheSpider ma potresti avere una classe nidificata chiamata 'Fo' con una classe nidificata chiamata' o'. –

+0

Oh, in realtà, vedo - c'è un '1' presente nel nome della classe locale. –

0

Come dimostrato dalla risposta di @AndyTurner non si può derivare il nome semplice dalla stringa di classe qualificato in tutte le casi.

Ma se il vincolo senza in realtà il tentativo di caricare la classe non vieta di leggere il contenuto del file di classe, si potrebbe procedere come segue (per i casi limite):

  1. Prendi un InputStream per il contenuto del file di classe tramite Class.getResourceAsStream()
  2. Analizzare l'inizio del file di classe e leggere il nome di super classe dal pool costante.
  3. (come commentato da @shmosel) Implementare la logica di Class.getSimpleName(). Il nome di super classe ti consente di sostituire Class.getSimpleBinaryString() che si basa su una classe già caricata.
+1

Questo sembra molto divertente invece di caricare la classe. –

+0

@AndyTurner l'OP saprà se ne vale la pena. – wero

Problemi correlati