2010-01-15 13 views
6

estoy usando Hibernate validador y tratando de crear un poco de clase util:Pregunta de genéricos de Java - Clase <T> vs. T?

public class DataRecordValidator<T> { 
    public void validate(Class<T> clazz, T validateMe) { 
     ClassValidator<T> validator = new ClassValidator<T>(clazz); 
     InvalidValue[] errors = validator.getInvalidValues(validateMe); 
     [...] 
    } 
} 

La pregunta es, ¿por qué necesito para suministrar el parámetro Class<T> clazz al ejecutar new ClassValidator<T>(clazz)? ¿Por qué no se puede especificar:

  1. T como en ClassValidator<T>(T)?
  2. validateMe.getClass() como en ClassValidator<T>(validateMe.getClass())

recibo mensajes de error cuando trato de hacer las dos opciones.

Editar: Entiendo por qué # 1 no funciona. Pero no entiendo por qué el # 2 no funciona. Actualmente me sale este error con # 2:

cannot find symbol 
symbol : constructor ClassValidator(java.lang.Class<capture#279 of ? extends java.lang.Object>) 
location: class org.hibernate.validator.ClassValidator<T> 

Nota: método de la API de Hibernate es (here)

Respuesta

1

Si el método validate es suyo, entonces puede omitir con seguridad el atributo Class.

public void validate(T validateMe) { 
    ClassValidator<T> validator = 
      new ClassValidator<T>((Class<T>) validateMe.getClass()); 
    ... 
} 

Pero el ClassValidator constructor requiere un argumento Class.

Usando un reparto insegura no es preferido, pero en este caso en realidad es seguro si no tiene algo como esto:

class A {..} 
class B extends A {..} 

new DataRecordValidator<A>.validate(new B()); 

Si cree que tendrá que hacer algo por el estilo, incluyen el argumento Class en el método. De lo contrario, puede obtener ClassCastException en tiempo de ejecución, pero esto se puede depurar fácilmente, aunque no es la idea detrás de los genéricos.

+0

Lamentablemente no funciona, ver mi respuesta a la publicación de @ Jherico. –

+0

Hice una actualización, debería estar funcionando. – Bozho

+0

Gracias, el '(Clase )' fue la clave! –

0

Debido ClassValidator está requiriendo un objeto de clase como parámetro, no una instancia de la clase en cuestión. Tenga en cuenta que usted podría ser capaz de hacer lo que estamos tratando de hacer con este código:

ClassValidator<? extends T> validator = new ClassValidator<? extends T>(validateMe.getClass()); 
+0

Gracias. ¿Por qué no puedes usar 'validateMe.getClass()' o 'T.class'? –

+0

Pensé que también ... pero me aparece este error: 'no se puede encontrar el símbolo' /' símbolo: constructor ClassValidator (java.lang.Class ) '/' ubicación: clase org.hibernate.validator.ClassValidator ' –

+0

Mira mi edición sobre cómo declarar tu ClassValidator – Jherico

8

Debido T no es un valor - es sólo una sugerencia para el compilador. La JVM no tiene idea del T. Puede usar genéricos solo como un tipo para fines de comprobación de tipos en tiempo de compilación.

+0

Gracias. ¿Por qué entonces no puedes usar 'validateMe.getClass()'? –

+1

Puedes __can__ usar 'getClass()' en cualquier referencia de objeto ... Simplemente marcado, el compilador está de acuerdo con eso. –

+2

Puede usar 'validateMe.getClass() ', pero hay advertencias: si' validateMe' es 'null' obtienes' NullPointerException', que puede ser o no lo que quieras. Y usando el código actual, podría aprobar una clase base (por ejemplo, validar esta instancia de 'Empleado' usando las reglas para su clase base' Persona'). Si omite el parámetro 'Clase 'que ya no es posible. –

Cuestiones relacionadas