【问题标题】:Java generics question - Class<T> vs. T?Java 泛型问题 - Class<T> 与 T?
【发布时间】:2010-01-15 21:07:42
【问题描述】:

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

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

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

  1. TClassValidator&lt;T&gt;(T) 一样吗?
  2. validateMe.getClass()ClassValidator&lt;T&gt;(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>

注意:Hibernate API 方法是 (here)

【问题讨论】:

    标签: java generics hibernate-validator


    【解决方案1】:

    因为T 不是一个值——它只是给编译器的一个提示。 JVM 不知道T。您只能将泛型用作一种类型,以便在编译时进行类型检查。

    【讨论】:

    • 谢谢。那为什么不能使用validateMe.getClass()
    • 可以在任何对象引用上使用getClass()...刚刚检查过,编译器可以接受。
    • 您可以使用validateMe.getClass(),但有一些注意事项:如果validateMenull,您会得到NullPointerException,这可能是也可能不是您想要的。并且使用当前代码,您可以传递一个基类(例如,使用其基类Person 的规则验证这个Employee 实例)。如果您遗漏了不再可能的Class 参数。
    【解决方案2】:

    如果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,但这很容易调试,尽管这不是泛型背后的想法。

    【讨论】:

    • 谢谢,(Class&lt;T&gt;) 是关键!
    【解决方案3】:

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

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

    【讨论】:

    • 谢谢。为什么不能使用validateMe.getClass()T.class
    • 我也这么认为...但我收到此错误:cannot find symbol / symbol : constructor ClassValidator(java.lang.Class&lt;capture#454 of ? extends java.lang.Object&gt;) / location: class org.hibernate.validator.ClassValidator&lt;T&gt;
    • 不:found : ? extends T / required: class or interface without bounds , symbol : method getInvalidValues(T) location: class org.hibernate.validator.ClassValidator&lt;capture#536 of ? extends T&gt;
    猜你喜欢
    • 2011-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-01
    • 2011-07-09
    • 1970-01-01
    相关资源
    最近更新 更多