Вопрос об обобщении Java - класс <T>против T? - PullRequest
7 голосов
/ 16 января 2010

Я использую валидатор 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);
        [...]
    }
}

Вопрос в том, зачем мне вводить параметр 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>

Примечание. Метод Hibernate API: ( здесь )

Ответы [ 3 ]

8 голосов
/ 16 января 2010

Потому что T это не значение - это просто подсказка для компилятора. JVM не имеет ни малейшего представления о T. Вы можете использовать дженерики только как тип для проверки типов во время компиляции.

1 голос
/ 16 января 2010

Если метод 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 во время выполнения, но это легко отладить, хотя это не совсем идея генериков.

0 голосов
/ 16 января 2010

Поскольку ClassValidator требует в качестве параметра объект Class, а НЕ экземпляр рассматриваемого класса.Имейте в виду, что вы можете сделать то, что пытаетесь сделать с помощью этого кода:

ClassValidator<? extends T> validator = new ClassValidator<? extends T>(validateMe.getClass());
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...