Java泛型问题 - Class <T>与T?

Mar*_*eon 7 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);
        [...]
    }
}
Run Code Online (Sandbox Code Playgroud)

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

  1. T如在ClassValidator<T>(T)
  2. validateMe.getClass() 如在 ClassValidator<T>(validateMe.getClass())

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

编辑:我明白为什么#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>
Run Code Online (Sandbox Code Playgroud)

注意:Hibernate API方法是(这里)

Ond*_*žka 8

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

  • 您可以使用`validateMe.getClass()`,但有一些警告:如果`validateMe`为`null`,您会得到一个`NullPointerException`,它可能是您想要的,也可能不是.使用当前代码,您可以传递基类(例如,使用其基类`Person`的规则验证此`Employee`实例).如果省略了不再可能的`Class`参数. (2认同)

Boz*_*zho 1

如果该validate方法是您的,那么您可以安全地跳过该Class属性。

public void validate(T validateMe) {
    ClassValidator<T> validator = 
           new ClassValidator<T>((Class<T>) validateMe.getClass());
    ...
}
Run Code Online (Sandbox Code Playgroud)

ClassValidator构造函数需要一个Class参数。

使用不安全的强制转换不是首选,但在这种情况下,如果您没有这样的东西,它实际上是安全的:

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

new DataRecordValidator<A>.validate(new B());
Run Code Online (Sandbox Code Playgroud)

如果您认为需要执行类似操作,请Class在方法中包含参数。否则,您可能会ClassCastException在运行时遇到问题,但这很容易调试,尽管这不完全是泛型背后的想法。