Pregunta

Si declarar una clase como un campo:

Class fooClass;

Eclipse me da la advertencia:

  

clase es un tipo cruda. Referencia a   Tipo de la clase genérica debe ser   parametrizada

¿Qué significa esto en la práctica? y por qué estoy insté a hacerlo? Si le pido Eclipse para una "solución rápida" me da:

Class<?> fooClass;

que no parece añadir mucho valor, pero ya no se da una advertencia.

EDIT: ¿Por qué es genérico Clase? Podría, por favor dar un ejemplo de parametrización, es decir, puede haber un uso válido de algo que no sea <?>?

EDIT: WOW! No me había dado cuenta de la profundidad de este. También he visto el Java Puzzler y ciertamente me asustó sobre las trampas de oso. Así que voy a utilizar siempre

Class<MyString> myStringClass = MyString.class;

en lugar de

Class myStringClass = MyString.class;

(Pero después de haber utilizado Java desde el primer día, realmente no me aviso cuando se convirtió en la clase genérica);

NOTA: Tengo @oxbow_lakes aceptadas ya que esto tiene sentido para mí, pero es claramente un área muy complicada. Insto a todos los programadores utilizar el Class<MyString> específico en lugar de Class. Y Class<?> es mucho más seguro que Class.

¿Fue útil?

Solución

Tipos primas e ilimitado comodines

Ninguna de las respuestas anteriores tienen realmente abordados por las que debe preferir Class<?> sobre Class, como en la cara de ella, el antiguo no parece ofrecer más información que la segunda.

La razón es que, la tipo raw , es decir Class, evita que el compilador de realizar el control de tipo genérico. Es decir, si utiliza tipos primas, subvert el tipo de sistema . Por ejemplo:

public void foo(Class<String> c) { System.out.println(c); }

Puede ser llamado thusly (lo hará tanto compilación y Ejecutar):

Class r = Integer.class
foo(r); //THIS IS OK (BUT SHOULDN'T BE)

Pero no por:

Class<?> w = Integer.class
foo(w); //WILL NOT COMPILE (RIGHTLY SO!)

Por siempre utilizando la forma no prima, incluso cuando debe utilizar ? porque no se puede saber cuál es el tipo de parámetro es (o está limitada por), se permite que el compilador para razonar acerca de la exactitud de su programa de forma más completa que si que utilizó tipos primas.


¿Por qué tienen tipos de primas en absoluto?

El Java Language Specification dice:

  

El uso de tipos de primas sólo se permite como una concesión a la compatibilidad de código heredado

Siempre se debe evitar. El ? comodín sin límites es probablemente mejor descrito en otra parte pero esencialmente medios "este es parametrizado en algún tipo, pero no saben (o atención) lo que es" . Esto no es lo mismo que tipos primas , que son una abominación y no existen en otros idiomas con los genéricos, como Scala .


¿Por qué es la clase parametrizada?

Bueno, aquí es un caso de uso. Supongamos que tengo un poco de interfaz de servicio:

public interface FooService

Y quiero para inyectar una implementación de la misma, utilizando una propiedad del sistema para definir la clase a utilizar.

Class<?> c = Class.forName(System.getProperty("foo.service"));

No sé en este punto que mi clase, es la correcta type

//next line throws ClassCastException if c is not of a compatible type
Class<? extends FooService> f = c.asSubclass(FooService.class); 

Ahora puede crear instancias de un FooService:

FooService s = f.newInstance(); //no cast

Otros consejos

  

que no parece añadir mucho valor   pero ya no se da una advertencia.

Tienes razón. Pero esto podría agregar valor:

Class<FooClass> fooClass;

o, si más apropiado:

Class<? extends FooClass> fooClass;

o

Class<FooInterface> fooClass;

Al igual que con los genéricos en general, se puede mejorar la seguridad de tipos especificando ¿qué tipo de la clase que desea la variable de espera. La advertencia contra los tipos de primas es sólo la intención de atrapar trozos de código que no se utiliza este potencial. Al declarar Class<?> que básicamente está diciendo "esto es significa para celebrar cualquier tipo de clase".

Debido a que, ya que JDK 5, Class ahora ha tener tipo parametrizado, lo que hace Class un objeto genérico. Esto es necesario (desde la introducción de los genéricos) para el compilador para hacer la comprobación de tipos (en tiempo de compilación, por supuesto).

Class<?> significa una "clase de desconocido" donde ? es un genéricos comodín . Significa que fooClass de tipo Class<?> acepta una Class cuyo tipo de partidos nada.

ejemplo típico:

Class<?> classUnknown = null;
classUnknown = ArrayList.class; //This compiles.

Puede, efectivamente, ha proporcionado un tipo parametrizado para ser más específicos, por ejemplo:.

Class<ArrayList> = ArrayList.class;

PS Tenga en cuenta, que no Class<List> listClass = ArrayList.class; compilar (a pesar de que es ArrayList de la lista), pero (como Mark Peters menciona en el comentario) hace Class<? extends List> listClass = ArrayList.class; de compilación (gracias al comodín).

El Javadoc de la clase href="http://download.oracle.com/javase/6/docs/api/java/lang/Class.html" rel="nofollow"> da una idea acerca de por qué existen parámetros de tipo para esta clase:

  

T - el tipo de la clase de modelado por   este objeto Class. Por ejemplo, el   tipo de String.class es Class<String>.   Uso Class<?> si el ser de clase   modelada es desconocida.

El uso de este tipo de parámetro no es tan obvio, pero un rápido vistazo al código fuente de la clase, indica por qué el parámetro de tipo a veces es necesario. Considerar la implementación del método newInstance:

    public T newInstance() 
        throws InstantiationException, IllegalAccessException
    {
    if (System.getSecurityManager() != null) {
        checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader());
    }
    return newInstance0();
    }

Si uno no ha notado, el tipo del objeto devuelto por este método es el del parámetro de tipo. Esto es útil en el código que utiliza una gran cantidad de reflexión, y donde a uno le gustaría tener mucho cuidado para asegurar que los objetos del tipo de derecho se crean instancias.

Teniendo en cuenta el ejemplo de la pregunta, si la instancia de clase en cambio se declara como:

Class<String> fooClass;
Class<Integer> barClass;
String aString;

entonces, es casi imposible tener el siguiente código para compilar:

aString = barClass.newInstance();

En resumen, si usted va a estar trabajando con jerarquías de clases y desea imponer estrictos controles de tiempo de compilación para asegurarse de que su código no tiene que realizar una gran cantidad de cheques instanceof, entonces es mejor que especifica el tipo de la clase que desea utilizar. Especificando ? permite todo tipo, pero no habría casos en los que tendrá que ser más específico.

Debido a que el uso de tipos primas en lugar de tipos parametrizados tiene muchas trampas.

Una de ellas es que si se utiliza un tipo de prima, se pierden todos los genéricos en la clase. Incluso aquellos definidos por cada método.

scroll top