2009-03-11 23 views
6

Vorrei implementare un metodo che accetta un argomento come Object, lo inserisce in un tipo arbitrario e, in caso di esito negativo, restituisce null. Ecco quello che ho finora:Generics Java

public static void main(String[] args) { 
    MyClass a, b; 
    a = Main.<MyClass>staticCast(new String("B")); 
} 

public static class MyClass { 
} 

public static <T> T staticCast(Object arg) { 
    try { 
     if (arg == null) return null; 
     T result = (T) arg; 
     return result; 
    } catch (Throwable e) { 
     return null; 
    } 
} 

Purtroppo l'eccezione di classe cast è mai buttato/catturato nel corpo della funzione staticCast(). Sembra che il compilatore Java generi la funzione String staticCast(Object arg) in cui è presente una riga String result = (String) arg; anche se io dico esplicitamente che il tipo di modello deve essere MyClass. Qualsiasi aiuto? Grazie.

+0

A proposito, dovresti prendere g solo ClassCastException, non Throwable. La cattura di Throwable può causare seri problemi. –

risposta

10

Poiché le informazioni di tipo generico viene cancellata in fase di esecuzione, il modo standard di gettare a un tipo generico è con un oggetto Class:

public static <T> T staticCast(Object arg, Class<T> clazz) { 
    if (arg == null) return null; 
    if (!clazz.isInstance(arg)) 
     return null; 
    T result = clazz.cast(arg); 
    return result; 
} 

Poi chiamare in questo modo:

a = Main.staticCast("B", MyClass.class); 
+0

utilizzando Class.isInstance sarebbe più diretto. –

+0

hmm, clazz? è come un klass? –

+0

isInstance funziona solo se l'oggetto è un'istanza di clazz, non se è una sottoclasse di clazz. isAssignableFrom funzionerà su tutto ciò che è valido per clazz, anche per le sottoclassi. –

6

Non puoi fare quello che vuoi ... almeno non in questo modo. Il compilatore ha rimosso tutte le informazioni in modo da finire con (T) essere Object nel cast - e questo funziona.

Il problema è che in seguito si sta facendo oggetto MyClass = (String); e quello non è permesso.

È stato ignorato il controllo dei compilatori e reso impossibile durante il runtime.

Quindi cosa stai cercando di fare esattamente? Se ci dici perché vuoi farlo, probabilmente possiamo dirti il ​​modo di farlo in Java.

Dato il tuo commento si potrebbe provare qualcosa di simile:

public class Main 
{ 
    public static void main(String[] args) 
    { 
     String a; 
     MyClass b; 
     a = staticCast(new String("B"), String.class); 
     b = staticCast(new String("B"), MyClass.class); 
     System.out.println(a); 
    } 

    public static class MyClass 
    { 
    } 

    public static <T> T staticCast(Object arg, final Class clazz) 
    { 
     // edit - oops forgot to deal with null... 
     if(arg == null) 
     { 
      return (null); 
     } 

     // the call to Class.cast, as mmeyer did, might be better... probably is better... 
     if(arg.getClass() != clazz) 
     { 
      // Given your answer to Ben S... 
      return (null); 

      // throw new ClassCastException("cannot cast a " + arg.getClass() + " to a " + clazz); 
     } 

     return ((T)arg); 
    } 
} 
+0

Vedo, quindi T è un oggetto nel cast. Voglio un metodo separato per ogni T che getterà l'argomento a (T), e se fallisce, viene catturata e non lanciata un'eccezione.Secondo Paul Tomblin (sotto il post) non succederà. – Budric

+0

il codice che ho fornito nella modifica dovrebbe fare quello che vuoi – TofuBeer

1

Non confondere generici Java per i modelli C++. C'è solo andare a essere un metodo staticCast che si chiama con il diverso tipo la cancellazione, non uno per ogni T.

Non usando Generics a tutti, vorrei scrivere in questo modo:

public static void main(String[] args) { 
    MyClass a, b; 
    a = (MyClass)Main.staticCast(new String("B"), MyClass.class); 
} 

public static class MyClass { 
} 

public static staticCast(Object arg, Class class) { 
     if (arg != null && class.isAssignableFrom(arg)) 
      return arg; 
     return null; 
} 

o rubare da un altro risposta, utilizzando generici:

public static <T> T staticCast(Object arg, Class<T> class) { 
     if (arg != null && class.isAssignableFrom(arg)) 
     { 
      T result = class.cast(arg); 
      return result; 
     } 
     return null; 
} 
+0

Ho dimenticato che CCE era un RuntimeException e non richiedeva un blocco catch, o lo avrei fatto come il tuo secondo metodo in origine. –

+0

Puoi spiegare perché il compilatore Java non genera la funzione MyClass staticCast (Object arg); quando specifichi esplicitamente il tipo T nella riga: a = Main. staticCast (new String ("B")); L'ho detto esplicitamente a ... Ho pensato Un link ad alcune letture sarebbe fantastico. – Budric

+0

@Budric: prova http://java.sun.com/docs/books/tutorial/java/generics/erasure.html. Inoltre, cerca le domande contrassegnate [java] [generics]. Ce ne sono di interessanti in giro. –

4

Intendi come Class<T>.cast(Object obj)?

Qualcosa di simile:

Class.forName("YourClass").cast(obj); 

dovrebbe fare più o meno ciò che si desidera.

Essere consapevoli del fatto che questo è abbastanza puzzolente e probabilmente è un segno di design scadente.

+0

Grazie. Il problema è che lanciare un'eccezione cast di classe se fallisce. È identico al codice: oggetto (YourClass) e ricevi un'eccezione generata da un errore che devi controllare ogni volta che usi quella linea di codice. Mi piacerebbe catturare e nascondere quell'eccezione nel metodo cast(). – Budric

+0

Vuoi asSubclass o getConstructor(). NewInstance(). Cast? –

1

Io sono d'accordo con Ben, tuttavia, preferisco la seguente notazione:

MyClass.class.cast(obj);