2010-01-15 4 views
6

Ich verwende Hibernate Validator und zu versuchen, ein wenig util Klasse zu erstellen:Java Generika Frage - Klasse <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); 
     [...] 
    } 
} 

Frage ist, warum muss ich den Class<T> clazz Parameter liefern, wenn new ClassValidator<T>(clazz) Ausführung? Warum können Sie nicht Folgendes angeben:

  1. T wie in ClassValidator<T>(T)?
  2. validateMe.getClass() wie in ClassValidator<T>(validateMe.getClass())

ich Fehler, wenn ich versuchen, beide Optionen zu tun.

Bearbeiten: Ich verstehe, warum # 1 nicht funktioniert. Aber ich verstehe nicht, warum # 2 nicht funktioniert. Ich erhalte derzeit diesen Fehler mit # 2:

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

Hinweis: Hibernate-API-Methode ist (here)

Antwort

1

Wenn die Methode validate Ihnen gehört, können Sie die ClassAttribute sicher überspringen.

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

Aber der ClassValidator Konstruktor erfordert ein Class Argument.

eine unsichere Guss Verwendung ist nicht bevorzugt, aber in diesem Fall ist es wirklich sicher, wenn Sie so etwas wie dieses nicht haben:

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

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

Wenn Sie denken, Sie so etwas tun müssen, um, umfassen das Class Argument in der Methode. Andernfalls erhalten Sie möglicherweise zur Laufzeit ClassCastException, aber dies ist leicht debuggbar, obwohl es nicht ganz die Idee hinter Generika ist.

+0

Leider funktioniert nicht, siehe meine Antwort auf @ Jhericos Beitrag. –

+0

Ich habe ein Update gemacht, es sollte funktionieren. – Bozho

+0

Danke, die '(Klasse )' war der Schlüssel! –

0

Da ClassValidator ein Klassenobjekt als Parameter erfordern, nicht eine Instanz der Klasse in Frage. Bedenken Sie könnten Sie in der Lage sein zu tun, was Sie versuchen, mit diesem Code zu tun:

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

Danke. Warum kannst du 'validateMe.getClass()' oder 'T.class' nicht verwenden? –

+0

Ich dachte das auch ... aber ich bekomme diesen Fehler: 'kann Symbol nicht finden' /' symbol: Konstruktor ClassValidator (java.lang.Class ) '/' location: Klasse org.hibernate.validator.ClassValidator ' –

+0

Schauen Sie sich meine Bearbeitung an, wie Sie Ihren ClassValidator deklarieren – Jherico

8

Da T kein Wert ist - es ist nur ein Hinweis für den Compiler. Die JVM hat keine Ahnung von T. Sie können Generika nur als Typ für die Typprüfung zur Kompilierzeit verwenden.

+0

Danke. Warum können Sie 'validateMe.getClass()' nicht verwenden? –

+1

Sie __can__ verwenden 'getClass()' auf jedem Objektreferenz ... Nur überprüft, Compiler ist OK damit. –

+2

Sie können validateMe verwenden.getClass() ', aber es gibt Vorbehalte: Wenn' validateMe' 'null' ist, erhalten Sie eine' NullPointerException', die möglicherweise nicht das ist, was Sie wollen. Und mit dem aktuellen Code könnten Sie eine Basisklasse übergeben (z. B. diese "Mitarbeiter" -Instanz anhand der Regeln für ihre Basisklasse "Person" validieren). Wenn Sie den Parameter "Class" weglassen, der nicht mehr möglich ist. –