Java泛型问题 - 类<t>与T?</t>

时间:2010-01-15 21:07:42

标签: java generics hibernate-validator

我正在使用Hibernate验证器并尝试创建一个小类util:

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

问题是,为什么我在执行Class<T> clazz时需要提供new ClassValidator<T>(clazz)参数?为什么不指定:

  1. TClassValidator<T>(T)一样?
  2. validateMe.getClass()ClassValidator<T>(validateMe.getClass())
  3. 一样

    当我尝试两种选择时,我会收到错误。

    编辑:我理解为什么#1不起作用。但我不明白为什么#2不起作用。我目前在#2中遇到此错误:

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

    注意:Hibernate API方法是(here

3 个答案:

答案 0 :(得分:8)

因为T不是值 - 它只是编译器的提示。 JVM没有T的线索。您只能将泛型用作类型,以便在编译时进行类型检查。

答案 1 :(得分:1)

如果validate方法属于您,则可以安全地跳过Class属性。

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

但是ClassValidator构造函数需要Class参数。

使用不安全的演员表不是首选,但在这种情况下,如果您没有这样的话,它实际上是安全的:

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

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

如果您认为需要执行此类操作,请在方法中包含Class参数。否则你可能会在运行时获得ClassCastException,但这很容易调试,虽然它不是泛型背后的想法。

答案 2 :(得分:0)

因为ClassValidator需要Class对象作为其参数,所以不是相关类的实例。请记住,您可以使用此代码执行您要执行的操作:

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