Domanda

Mi chiedevo che cosa è il tipo di dati della variabile di modello se il ritorno è impostato su un modello. Ho visto questo in un codice da qualche parte, ma non so dove lo fa il cast del valore recuperato dalla sessione.

public class RequestObject {
    public <T> T getFromSessionMap(String sessionKey) {
        return (T)session.getAttribute(sessionKey);
    }
}

Il codice per questa esterna è:

MyClassType type = request.getFromSessionMap("abc");

La linea incontra ClassCastException in fase di lancio per il mio oggetto. Ma quando aggiungo a guardare session.getAttribute ( "abc"), dimostra che il tipo è MyClassType. Qualsiasi aiuto sarebbe apprezzato.

A quanto pare questo codice speciale per l'utilizzo di template rende il ritorno di getFromSessionMap un tipo di variabile e quindi c'è bisogno di un cast. Questo funziona su tutti i casi, ma improvvisamente non è riuscito in una parte del codice.

È stato utile?

Soluzione

  

A quanto pare questo codice speciale per l'utilizzo   modello fa il ritorno di   getFromSessionMap un tipo variabile e   quindi senza necessità di un cast.

Fondamentalmente, ci deve essere un typecast da qualche parte tra ottenere il risultato del session.getAttribute(sessionKey) e l'assegnazione a MyClassType. Il linguaggio Java (e la JVM) non permetteranno un oggetto che non è un'istanza MyClassType (o un sottotipo della stessa) da assegnare a una variabile MyClassType.

Non importa come si scrive il codice, un typecast deve avvenire . E dal momento che l'attributo (apparentemente) non è un MyClassType (o sottotipo), si stanno ottenendo un ClassCastException.

Quindi la vera domanda è perché non sei sempre un errore di compilazione? E la risposta è la @SuppressWarnings("unchecked")! Se è stato rimosso questo avvertimento, si otterrebbe un messaggio di errore "tipo di conversione non sicuro" per questa linea:

return (T) session.getAttribute(sessionKey);

In realtà, Java non può fare una (vera) cast di tipo a un tipo generico. E questo è ciò che il messaggio di errore / avvertimento è lì per sottolineare. In realtà, una volta che il codice è stato compilato, questo codice

public <T> T getFromSessionMap(String sessionKey) {
    return (T)session.getAttribute(sessionKey);
}

è in realtà non è diversa nel senso da questo:

public Object getFromSessionMap(String sessionKey) {
    return session.getAttribute(sessionKey);
}

Tecnicamente questo è chiamato "cancellazione di tipo".

Allora, dove è il tipo di controllo / typecast in realtà avvenendo? La risposta è in questa linea:

MyClassType type = request.getFromSessionMap("abc");

Anche se non avete scritto un typecast qui, il codice generato dal compilatore Java fa un typecast prima di assegnare il valore a type. Deve. Perché per quanto a sua conoscenza, l'istanza si sta assegnando potrebbe essere qualsiasi tipo di oggetto.

altri utenti hanno suggerito l'aggiunta di un argomento di classe a getFromSessionMap. Di per sé questo non fa assolutamente nulla . Se anche si sostituisce il corpo del metodo con:

return clazz.cast(session.getAttribute(sessionKey));

si farà sì che il metodo per fare in realtà un vero e proprio controllo di tipo. Ma questa unica causa ClassCastException per essere gettato in un posto diverso. E l'istruzione di assegnazione sarà ancora fare un cast di tipo nascosto !!

Altri suggerimenti

Nell'esempio della domanda, il tipo di ritorno è T. Il tipo cancellato verrà Object come, implicitamente, T extends Object. Il cast effettivo viene eseguito nel bytecode del metodo chiamante (è possibile utilizzare javap -c vedere che).

In generale, è consigliabile mantenere il numero di oggetti "di alto livello" in sessioni più piccolo possibile. Uno dei vantaggi di fare questo, non c'è più la necessità di metodi hacky come questi.

  

Qualsiasi aiuto sarebbe apprezzato, perché il mio codice incontra ClassCastException.

Se stai ricevendo un ClassCastException, questo significa che si sta cercando di gettare qualcosa in qualcosa che non è, come nel codice seguente:

Map session = new HashMap();
session.put("date", "2009-11-12");
Date today = (Date) session.get("date"); // tries to convert String to Date

Il ClassCastException dovrebbe avere un messaggio di particolare illuminante, come "java.lang.String non può essere gettato a java.util.Date".

Si utilizza tipo gettato all'interno del corpo del metodo ( '(T) session.getAttribute (SessionKey)' ).

Ciò significa che si dice in modo esplicito a compilatore 'Sono assolutamente sicuro che oggetto restituito è-A T e pronti a gestire l'errore se non è' .

Ecco tua ipotesi sul tipo di attributo non è corretto e hai un errore. Quindi, tutto ciò che è corretto e runtime fornisce già con il tipo di oggetto di attributo reale che non è IS-A MyClassType.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top