¿Cómo puedo responder a las advertencias de reparto sin marcar?


Eclipse me está dando una advertencia de la siguiente forma:

Tipo de seguridad: Sin marcar fundido de Objeto a HashMap

Esto es de una llamada a una API que no tengo control sobre qué devuelve el Objeto:

HashMap<String, String> getItems(javax.servlet.http.HttpSession session) {
  HashMap<String, String> theHash = (HashMap<String, String>)session.getAttribute("attributeKey");
  return theHash;
}

Me gustaría evitar las advertencias de Eclipse, si es posible, ya que teóricamente indican al menos un problema potencial de código. No he encontrado una buena manera de eliminar este todavía, sin embargo. Puedo extraer la sola línea involucrada a un método por sí mismo y agregue @SuppressWarnings("unchecked") a ese método, limitando así el impacto de tener un bloque de código donde ignoro las advertencias. ¿Alguna opción mejor? No quiero desactivar estas advertencias en Eclipse.

Antes de llegar al código, era más simple, pero aún así provocaba advertencias:

HashMap getItems(javax.servlet.http.HttpSession session) {
  HashMap theHash = (HashMap)session.getAttribute("attributeKey");
  return theHash;
}

El problema estaba en otra parte cuando intentabas usar el hash recibías advertencias:

HashMap items = getItems(session);
items.put("this", "that");

Type safety: The method put(Object, Object) belongs to the raw type HashMap.  References to generic type HashMap<K,V> should be parameterized.
Author: Chris Stillwell, 2009-02-04

24 answers

La respuesta obvia, por supuesto, no es hacer el reparto sin control.

Si es absolutamente necesario, al menos intente limitar el alcance de la anotación @SuppressWarnings. Según sus Javadocs , puede ir sobre variables locales; de esta manera, ni siquiera afecta a todo el método.

Ejemplo:

@SuppressWarnings("unchecked")
Map<String, String> myMap = (Map<String, String>) deserializeMap();

No hay manera de determinar si el Map realmente debe tener los parámetros genéricos <String, String>. Debe saber de antemano cuáles deben ser los parámetros (o encontrará hacia fuera cuando usted consigue un ClassCastException). Esta es la razón por la que el código genera una advertencia, porque el compilador no puede saber si es seguro.

 478
Author: Michael Myers,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-02-03 22:30:58

Desafortunadamente, no hay grandes opciones aquí. Recuerde, el objetivo de todo esto es preservar la seguridad del tipo. "Java Generics " ofrece una solución para tratar con bibliotecas heredadas no genéricas, y hay una en particular llamada "técnica de bucle vacío" en la sección sección 8.2. Básicamente, hacer el yeso inseguro, y suprimir la advertencia. Luego recorre el mapa de la siguiente manera:

@SuppressWarnings("unchecked")
Map<String, Number> map = getMap();
for (String s : map.keySet());
for (Number n : map.values());

Si se encuentra un tipo inesperado, obtendrá un tiempo de ejecución ClassCastException, pero al menos sucederá cerca de la fuente del problema.

 127
Author: Julien Chastang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-28 09:35:43

Wow, creo que encontré la respuesta a mi propia pregunta. ¡No estoy seguro de que valga la pena! :)

El problema es que el cast no está marcado. Así que tienes que comprobarlo tú mismo. No puede simplemente verificar un tipo parametrizado con instanceof, porque la información del tipo parametrizado no está disponible en tiempo de ejecución, ya que se ha borrado en tiempo de compilación.

Pero, puede realizar una verificación en todos y cada uno de los elementos del hash, con instanceof, y al hacerlo, puede construir un nuevo hash que es de tipo seguro. Y no provocarás ninguna advertencia.

Gracias a mmyers y Esko Luontola, he parametrizado el código que originalmente escribí aquí, para que pueda ser envuelto en una clase de utilidad en algún lugar y utilizado para cualquier HashMap parametrizado. Si quieres entenderlo mejor y no estás muy familiarizado con los genéricos, te animo a ver el historial de edición de esta respuesta.

public static <K, V> HashMap<K, V> castHash(HashMap input,
                                            Class<K> keyClass,
                                            Class<V> valueClass) {
  HashMap<K, V> output = new HashMap<K, V>();
  if (input == null)
      return output;
  for (Object key: input.keySet().toArray()) {
    if ((key == null) || (keyClass.isAssignableFrom(key.getClass()))) {
        Object value = input.get(key);
        if ((value == null) || (valueClass.isAssignableFrom(value.getClass()))) {
            K k = keyClass.cast(key);
            V v = valueClass.cast(value);
            output.put(k, v);
        } else {
            throw new AssertionError(
                "Cannot cast to HashMap<"+ keyClass.getSimpleName()
                +", "+ valueClass.getSimpleName() +">"
                +", value "+ value +" is not a "+ valueClass.getSimpleName()
            );
        }
    } else {
        throw new AssertionError(
            "Cannot cast to HashMap<"+ keyClass.getSimpleName()
            +", "+ valueClass.getSimpleName() +">"
            +", key "+ key +" is not a " + keyClass.getSimpleName()
        );
    }
  }
  return output;
}

Eso es mucho trabajo, posiblemente por muy poca recompensa... No estoy seguro si lo usaré o no. Yo aprecie cualquier comentario en cuanto a si la gente piensa que vale la pena o no. Además, apreciaría sugerencias de mejora: ¿hay algo mejor que pueda hacer además de lanzar AssertionErrors? ¿Hay algo mejor que pueda lanzar? ¿Debo hacer una excepción marcada?

 112
Author: skiphoppy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-27 14:41:21

En las preferencias de Eclipse, vaya a Java->Compiler->Errors/Warnings->Generic types y marque la casilla Ignore unavoidable generic type problems.

Esto satisface la intención de la pregunta, es decir,

Me gustaría evitar las advertencias de Eclipse...

Si no es el espíritu.

 49
Author: Dave,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-10-21 17:40:14

Puede crear una clase de utilidad como la siguiente y usarla para suprimir la advertencia sin marcar.

public class Objects {

    /**
     * Helps to avoid using {@code @SuppressWarnings({"unchecked"})} when casting to a generic type.
     */
    @SuppressWarnings({"unchecked"})
    public static <T> T uncheckedCast(Object obj) {
        return (T) obj;
    }
}

Puede usarlo de la siguiente manera:

import static Objects.uncheckedCast;
...

HashMap<String, String> getItems(javax.servlet.http.HttpSession session) {
      return uncheckedCast(session.getAttribute("attributeKey"));
}

Un poco más de discusión sobre esto está aquí: http://cleveralias.blogs.com/thought_spearmints/2006/01/suppresswarning.html

 23
Author: Esko Luontola,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-02-03 22:54:33

Esto es difícil, pero aquí están mis pensamientos actuales:

Si su API devuelve el objeto, entonces no hay nada que pueda hacer no no importa qué, estará emitiendo el objeto a ciegas. Permite que Java lance ClassCastExceptions, o puede verificar cada elemento usted mismo y lanzar Aserciones o IllegalArgumentExceptions o algo así, pero estas comprobaciones en tiempo de ejecución son todas equivalentes. Tienes que suprimir el tiempo de compilación sin marcar cast sin importar lo que hagas en ejecución.

Simplemente preferiría hacer un cast ciego y dejar que la JVM realice su comprobación de tiempo de ejecución por mí, ya que "sabemos" lo que la API debe devolver, y generalmente estamos dispuestos a asumir que la API funciona. Use genéricos en todas partes por encima del yeso, si los necesita. Realmente no estás comprando nada allí ya que todavía tienes el molde ciego simple, pero al menos puedes usar genéricos a partir de ahí para que la JVM pueda ayudarte a evitar los moldes ciegos en otras partes de tu código.

En este caso particular, presumiblemente se puede ver la llamada a setAttribute y ver el tipo está entrando, por lo que solo ciego-casting el tipo a la misma en la salida no es inmoral. Agregue un comentario que haga referencia al setAttribute y termine con él.

 19
Author: Dustin Getz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-02 15:01:45

En el mundo de la sesión HTTP realmente no se puede evitar el cast, ya que la API se escribe de esa manera (toma y devuelve solo Object).

Con un poco de trabajo se puede evitar fácilmente el reparto sin control, 'sin embargo. Esto significa que se convertirá en un molde tradicional dando un ClassCastException justo allí en caso de un error). Una excepción no marcada podría convertirse en un CCE en cualquier momento posterior en lugar del punto del lanzamiento (esa es la razón por la que es una advertencia separada).

Reemplazar el HashMap con una clase dedicada:

import java.util.AbstractMap;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class Attributes extends AbstractMap<String, String> {
    final Map<String, String> content = new HashMap<String, String>();

    @Override
    public Set<Map.Entry<String, String>> entrySet() {
        return content.entrySet();
    }

    @Override
    public Set<String> keySet() {
        return content.keySet();
    }

    @Override
    public Collection<String> values() {
        return content.values();
    }

    @Override
    public String put(final String key, final String value) {
        return content.put(key, value);
    }
}

Luego se envía a esa clase en lugar de Map<String,String> y todo se verificará en el lugar exacto donde escriba su código. No inesperado ClassCastExceptions más adelante.

 12
Author: Joachim Sauer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-02-04 16:59:20

Aquí hay un ejemplo abreviado que evita la advertencia de "lanzamiento no controlado" mediante el empleo de dos estrategias mencionadas en otras respuestas.

  1. Pasar la Clase del tipo de interés como parámetro en tiempo de ejecución (Class<T> inputElementClazz). Entonces usted puede utilizar: inputElementClazz.cast(anyObject);

  2. Para el tipo de fundición de una Colección, utilice el comodín ? en lugar de un tipo genérico T para reconocer que de hecho no sabe qué tipo de objetos esperar del código heredado (Collection<?> unknownTypeCollection). Después de todo, esto es lo que quiere decirnos la advertencia de "reparto no controlado": No podemos estar seguros de que obtenemos un Collection<T>, por lo que lo honesto es usar un Collection<?>. Si es absolutamente necesario, una colección de un tipo conocido todavía se puede construir (Collection<T> knownTypeCollection).

El código heredado interconectado en el ejemplo a continuación tiene un atributo "input" en el StructuredViewer (StructuredViewer es un widget de árbol o tabla, "input" es el modelo de datos detrás de él). Esta "entrada" podría ser cualquier tipo de Java Colección.

public void dragFinished(StructuredViewer structuredViewer, Class<T> inputElementClazz) {
    IStructuredSelection selection = (IStructuredSelection) structuredViewer.getSelection();
    // legacy code returns an Object from getFirstElement,
    // the developer knows/hopes it is of type inputElementClazz, but the compiler cannot know
    T firstElement = inputElementClazz.cast(selection.getFirstElement());

    // legacy code returns an object from getInput, so we deal with it as a Collection<?>
    Collection<?> unknownTypeCollection = (Collection<?>) structuredViewer.getInput();

    // for some operations we do not even need a collection with known types
    unknownTypeCollection.remove(firstElement);

    // nothing prevents us from building a Collection of a known type, should we really need one
    Collection<T> knownTypeCollection = new ArrayList<T>();
    for (Object object : unknownTypeCollection) {
        T aT = inputElementClazz.cast(object);
        knownTypeCollection.add(aT);
        System.out.println(aT.getClass());
    }

    structuredViewer.refresh();
}

Naturalmente, el código anterior puede dar errores de tiempo de ejecución si usamos el código heredado con los tipos de datos incorrectos (por ejemplo, si establecemos una matriz como "entrada" del StructuredViewer en lugar de una colección Java).

Ejemplo de llamar al método:

dragFinishedStrategy.dragFinished(viewer, Product.class);
 9
Author: StaticNoiseLog,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-27 18:27:37

En este caso particular, no almacenaría Mapas en la HttpSession directamente, sino una instancia de mi propia clase, que a su vez contiene un Mapa (un detalle de implementación de la clase). Entonces puede estar seguro de que los elementos en el mapa son del tipo correcto.

Pero si de todos modos desea comprobar que el contenido del mapa es del tipo correcto, podría usar un código como este:

public static void main(String[] args) {
    Map<String, Integer> map = new HashMap<String, Integer>();
    map.put("a", 1);
    map.put("b", 2);
    Object obj = map;

    Map<String, Integer> ok = safeCastMap(obj, String.class, Integer.class);
    Map<String, String> error = safeCastMap(obj, String.class, String.class);
}

@SuppressWarnings({"unchecked"})
public static <K, V> Map<K, V> safeCastMap(Object map, Class<K> keyType, Class<V> valueType) {
    checkMap(map);
    checkMapContents(keyType, valueType, (Map<?, ?>) map);
    return (Map<K, V>) map;
}

private static void checkMap(Object map) {
    checkType(Map.class, map);
}

private static <K, V> void checkMapContents(Class<K> keyType, Class<V> valueType, Map<?, ?> map) {
    for (Map.Entry<?, ?> entry : map.entrySet()) {
        checkType(keyType, entry.getKey());
        checkType(valueType, entry.getValue());
    }
}

private static <K> void checkType(Class<K> expectedType, Object obj) {
    if (!expectedType.isInstance(obj)) {
        throw new IllegalArgumentException("Expected " + expectedType + " but was " + obj.getClass() + ": " + obj);
    }
}
 8
Author: Esko Luontola,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-02-03 23:24:40

En Android Studio si quieres desactivar la inspección puedes usar:

//noinspection unchecked
Map<String, String> myMap = (Map<String, String>) deserializeMap();
 6
Author: Jan Moravec,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-01 20:22:35

Los Objetos.La función de utilidad sin marcar en la respuesta anterior de Esko Luontola es una excelente manera de evitar el desorden del programa.

Si no desea que los SuppressWarnings en un método completo, Java le obliga a ponerlo en un local. Si necesitas un cast en un miembro puede llevar a un código como este:

@SuppressWarnings("unchecked")
Vector<String> watchedSymbolsClone = (Vector<String>) watchedSymbols.clone();
this.watchedSymbols = watchedSymbolsClone;

Usar la utilidad es mucho más limpio, y todavía es obvio lo que está haciendo:

this.watchedSymbols = Objects.uncheckedCast(watchedSymbols.clone());

NOTA: Creo que es importante añadir que a veces la advertencia realmente significa que estás haciendo algo mal como:

ArrayList<Integer> intList = new ArrayList<Integer>();
intList.add(1);
Object intListObject = intList; 

 // this line gives an unchecked warning - but no runtime error
ArrayList<String> stringList  = (ArrayList<String>) intListObject;
System.out.println(stringList.get(0)); // cast exception will be given here

Lo que el compilador le está diciendo es que este cast NO se verificará en tiempo de ejecución, por lo que no se generará ningún error de tiempo de ejecución hasta que intente acceder a los datos en el contenedor genérico.

 5
Author: Gonen I,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-09 09:50:24

La supresión de advertencias no es una solución. No deberías hacer dos niveles de casting en una sola declaración.

HashMap<String, String> getItems(javax.servlet.http.HttpSession session) {

    // first, cast the returned Object to generic HashMap<?,?>
    HashMap<?, ?> theHash = (HashMap<?, ?>)session.getAttribute("attributeKey");

    // next, cast every entry of the HashMap to the required type <String, String>
    HashMap<String, String> returingHash = new HashMap<>();
    for (Entry<?, ?> entry : theHash.entrySet()) {
        returingHash.put((String) entry.getKey(), (String) entry.getValue());
    }
    return returingHash;
}
 4
Author: abbas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-03-13 20:57:34

Una conjetura rápida si publica su código puede decir con seguridad, pero es posible que haya hecho algo en las líneas de

HashMap<String, Object> test = new HashMap();

Que producirá la advertencia cuando necesite hacer

HashMap<String, Object> test = new HashMap<String, Object>();

Podría valer la pena mirar

Genéricos en el Lenguaje de programación Java

Si no está familiarizado con lo que hay que hacer.

 2
Author: Mark Davidson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-02-03 22:04:45

Puede que haya malinterpretado la pregunta(un ejemplo y un par de líneas circundantes sería bueno), pero ¿por qué no siempre se utiliza una interfaz adecuada (y Java5+)? No veo ninguna razón por la que quiera lanzar a un HashMap en lugar de un Map<KeyType,ValueType>. De hecho, no puedo imaginar ninguna razón para establecer el tipo de una variable en HashMap en lugar de Map.

¿Y por qué la fuente es un Object? Es un tipo de parámetro de una colección legacy? Si es así, utilice genéricos y especifique el tipo que querer.

 2
Author: phihag,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-02-03 22:05:08

Si tengo que usar una API que no soporta genéricos.. Intento aislar esas llamadas en rutinas de envoltura con el menor número de líneas posible. Después de eso uso la anotación Supresswarnings y también añadir los moldes de seguridad de tipo al mismo tiempo.

Esto es solo una preferencia personal para mantener las cosas lo más ordenadas posible.

 2
Author: Fortyrunner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-02-03 22:47:49

Tome este, es mucho más rápido que crear un nuevo HashMap, si ya es uno, pero sigue siendo seguro, ya que cada elemento se comprueba contra su tipo...

@SuppressWarnings("unchecked")
public static <K, V> HashMap<K, V> toHashMap(Object input, Class<K> key, Class<V> value) {
       assert input instanceof Map : input;

       for (Map.Entry<?, ?> e : ((HashMap<?, ?>) input).entrySet()) {
           assert key.isAssignableFrom(e.getKey().getClass()) : "Map contains invalid keys";
           assert value.isAssignableFrom(e.getValue().getClass()) : "Map contains invalid values";
       }

       if (input instanceof HashMap)
           return (HashMap<K, V>) input;
       return new HashMap<K, V>((Map<K, V>) input);
    }
 2
Author: jfreundo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-10-14 09:28:19

Simplemente typecheck antes de lanzarlo.

Object someObject = session.getAttribute("attributeKey");
if(someObject instanceof HashMap)
HashMap<String, String> theHash = (HashMap<String, String>)someObject;  

Y para cualquiera que pregunte, es bastante común recibir objetos donde no está seguro del tipo. Muchas implementaciones " SOA " heredadas pasan alrededor de varios objetos en los que no siempre debe confiar. (Los horrores!)

EDIT Cambió el código de ejemplo una vez para que coincida con las actualizaciones del póster, y después de algunos comentarios, veo que instanceof no funciona bien con los genéricos. Sin embargo, cambiar la comprobación para validar el exterior object parece jugar bien con el compilador de línea de comandos. Ejemplo revisado ahora publicado.

 1
Author: Rick,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-02-03 22:55:05

Casi todos los problemas en Ciencias de la Computación se pueden resolver añadiendo un nivel de indirección*, o algo así.

Así que introduce un objeto no genérico que es de un nivel superior a un Map. Sin contexto no va a parecer muy convincente, pero de todos modos:

public final class Items implements java.io.Serializable {
    private static final long serialVersionUID = 1L;
    private Map<String,String> map;
    public Items(Map<String,String> map) {
        this.map = New.immutableMap(map);
    }
    public Map<String,String> getMap() {
        return map;
    }
    @Override public String toString() {
        return map.toString();
    }
}

public final class New {
    public static <K,V> Map<K,V> immutableMap(
        Map<? extends K, ? extends V> original
    ) {
        // ... optimise as you wish...
        return Collections.unmodifiableMap(
            new HashMap<String,String>(original)
        );
    }
}

static Map<String, String> getItems(HttpSession session) {
    Items items = (Items)
        session.getAttribute("attributeKey");
    return items.getMap();
}

*Excepto demasiados niveles de indirección.

 1
Author: Tom Hawtin - tackline,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-02-04 15:46:45

Aquí hay una forma de manejar esto cuando anulo la operación equals().

public abstract class Section<T extends Section> extends Element<Section<T>> {
    Object attr1;

    /**
    * Compare one section object to another.
    *
    * @param obj the object being compared with this section object
    * @return true if this section and the other section are of the same
    * sub-class of section and their component fields are the same, false
    * otherwise
    */       
    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            // this exists, but obj doesn't, so they can't be equal!
            return false;
        }

        // prepare to cast...
        Section<?> other;

        if (getClass() != obj.getClass()) {
            // looks like we're comparing apples to oranges
            return false;
        } else {
            // it must be safe to make that cast!
            other = (Section<?>) obj;
        }

        // and then I compare attributes between this and other
        return this.attr1.equals(other.attr1);
    }
}

Esto parece funcionar en Java 8 (incluso compilado con -Xlint:unchecked)

 1
Author: Jim Daehn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-01-30 00:15:32

El problema está aquí:

... = (HashMap<String, String>)session.getAttribute("attributeKey");

El resultado de session.getAttribute(...) es object que podría ser cualquier cosa, pero ya que "saber" es un HashMap<String, String> sólo estás colada sin consultar primero. Por lo tanto, la advertencia. Para ser pedante, que Java quiere que seas en este caso, debes recuperar el resultado y verificar su compatibilidad con instanceof.

 0
Author: JMD,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-02-03 22:16:39

Si está seguro de que el tipo devuelto por la sesión.getAttribute () es HashMap, entonces no puede encasillar a ese tipo exacto, sino que solo debe verificar el HashMap genérico

HashMap<?,?> getItems(javax.servlet.http.HttpSession session) {  
    HashMap<?,?> theHash = (HashMap<?,?>)session.getAttribute("attributeKey");
    return theHash;
} 

Eclipse entonces sorprenderá las advertencias, pero por supuesto esto puede conducir a errores de tiempo de ejecución que pueden ser difíciles de depurar. Utilizo este enfoque no solo en contextos de operación crítica.

 0
Author: Lukas Normantas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-06-12 12:52:52

Dos formas, una que evita la etiqueta por completo, la otra utilizando un método de utilidad travieso pero agradable.
El problema son las Colecciones pre-genéricas...
Creo que la regla general es: "cast objects one thing at a time" - lo que esto significa cuando se trata de usar clases raw en un mundo genérico es porque no sabes lo que hay en este mapa, ?> (¡y de hecho la JVM podría incluso encontrar que ni siquiera es un Mapa!), es obvio cuando lo piensas que no puedes lanzarlo. Si tuvieras un Map map2 entonces HashSet keys = (HashSet)map2.keySet () no te da una advertencia, a pesar de ser un "acto de fe" para el compilador (porque podría resultar ser un conjunto de árboles)... pero es solo un soltero acto de fe.

PS a la objeción de que iterar como en mi primera manera " es aburrido "y" toma tiempo", la respuesta es" sin dolor no hay ganancia": una colección genérica está garantizada para contener Mapa.Entradas, y nada más. Usted tiene que pagar por esta garantía. Al usar genéricos sistemáticamente, este pago, bellamente, toma la forma de cumplimiento de codificación, ¡no tiempo de máquina!
Una escuela de pensamiento podría decir que debe establecer la configuración de Eclipse para hacer tales errores de casts sin verificar, en lugar de advertencias. En ese caso tendrías que usar mi primera forma.

package scratchpad;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Vector;

public class YellowMouse {

    // First way

    Map<String, String> getHashMapStudiouslyAvoidingSuppressTag(HttpSession session) {
      Map<?, ?> theHash = (Map<?, ?>)session.getAttribute("attributeKey");

      Map<String, String> yellowMouse = new HashMap<String, String>();
      for( Map.Entry<?, ?> entry : theHash.entrySet() ){
        yellowMouse.put( (String)entry.getKey(), (String)entry.getValue() );
      }

      return yellowMouse;
    }


    // Second way

    Map<String, String> getHashMapUsingNaughtyButNiceUtilityMethod(HttpSession session) {
      return uncheckedCast( session.getAttribute("attributeKey") );
    }


    // NB this is a utility method which should be kept in your utility library. If you do that it will
    // be the *only* time in your entire life that you will have to use this particular tag!!

    @SuppressWarnings({ "unchecked" })
    public static synchronized <T> T uncheckedCast(Object obj) {
        return (T) obj;
    }


}
 0
Author: mike rodent,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-24 22:40:48

Esto hace que las advertencias desaparezcan...

 static Map<String, String> getItems(HttpSession session) {
        HashMap<?, ?> theHash1 = (HashMap<String,String>)session.getAttribute("attributeKey");
        HashMap<String,String> theHash = (HashMap<String,String>)theHash1;
    return theHash;
}
 -1
Author: lukewm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-08-23 20:46:37

Solución: Desactive esta advertencia en Eclipse. No @ SuppressWarnings que, simplemente desactivarlo por completo.

Varias de las "soluciones" presentadas anteriormente están fuera de línea, haciendo que el código sea ilegible para suprimir una advertencia tonta.

 -3
Author: Marc Riehm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-28 20:27:30