В Java я хотел бы иметь что-то вроде:
class Clazz<T> {
static void doIt(T object) {
// ...
}
}
Но я получаю
Невозможно сделать статическую ссылку на нестатический тип T
Я не понимаю дженерики за пределами базового использования и поэтому не могу понять этого. Это не помогает, что я не смог найти много информации в Интернете по этому вопросу.
Может ли кто-нибудь уточнить, возможно ли такое использование подобным образом? Кроме того, почему моя первоначальная попытка оказалась неудачной?
источник
Java не знает, что
T
есть, пока вы не создадите экземпляр типа.Может быть, вы можете выполнять статические методы путем вызова,
Clazz<T>.doit(something)
но это звучит так, как будто вы не можете.Другой способ справиться с этим - поместить параметр типа в сам метод:
который не дает вам правильное ограничение на U, но это лучше, чем ничего ....
источник
Я столкнулся с этой же проблемой. Я нашел свой ответ, загрузив исходный код для
Collections.sort
в рамках Java. Ответ, который я использовал, заключался в том, чтобы поместить<T>
шаблон в метод, а не в определение класса.Так это сработало:
Конечно, после прочтения ответов выше я понял, что это будет приемлемой альтернативой без использования обобщенного класса:
источник
T extends XXX
синтаксис.Comparable
. Попробуй<T extends Comparable<? super T>>
вместо этого.Можно сделать то, что вы хотите, используя синтаксис для универсальных методов при объявлении вашего
doIt()
метода (обратите внимание на добавление<T>
междуstatic
иvoid
в сигнатуре методаdoIt()
):Я заставил редактор Eclipse принять приведенный выше код без
Cannot make a static reference to the non-static type T
ошибки, а затем расширил его до следующей рабочей программы (в комплекте с немного соответствующей возрасту культурной ссылкой):Который выводит эти строки на консоль, когда я ее запускаю:
источник
<T>
маскирует первую так же, как вclass C { int x; C(int x) { ... } }
параметреx
маскирует полеx
.static <E extends SomeClass> E foo(E input){return input;}
для каждого метода, когда я хотел бы сделать что-то вродеstatic <E extends SomeClass>; //static generic type defined only once and reused
static E foo(E input){return input;}
static E bar(E input){return input;}
//...etc...
Я думаю, что этот синтаксис еще не упоминался (в случае, если вы хотите метод без аргументов):
И звонок:
Надеюсь, это поможет кому-то.
источник
<String>
потому что он просто выводит аргумент типа, потому что вы присваиваете его переменной. Если вы не назначаете это, это просто делает выводObject
.Это правильно упоминается в ошибке: вы не можете сделать статическую ссылку на нестатический тип T. Причина в том, что параметр типа
T
может быть заменен любым аргументом типа, например,Clazz<String>
иClazz<integer>
т. Д. Но статические поля / методы являются общими для всех не предметы класса.Следующая выдержка взята из документа :
Как правильно указал Крис в своем ответе, вам нужно использовать параметр типа с методом, а не с классом в этом случае. Вы можете написать это так:
источник
Что-то вроде следующего приблизит вас
РЕДАКТИРОВАТЬ: обновленный пример с более подробной информацией
источник
Когда вы указываете универсальный тип для своего класса, JVM знает, что он имеет только экземпляр вашего класса, а не определения. Каждое определение имеет только параметризованный тип.
Обобщения работают как шаблоны в C ++, поэтому вы должны сначала создать экземпляр своего класса, а затем использовать функцию с указанным типом.
источник
Clazz<int>::doIt( 5 )
)Кроме того, проще говоря, это происходит из-за свойства Erasure для generics. Это означает, что хотя мы определяем
ArrayList<Integer>
иArrayList<String>
во время компиляции он остается как два разных конкретных типа, но во время выполнения JVM стирает универсальные типы и создает только один класс ArrayList вместо двух классов. Поэтому, когда мы определяем метод статического типа или что-то еще для универсального объекта, он используется всеми экземплярами этого универсального шаблона , в моем примере он используется совместно обоимиArrayList<Integer>
и.ArrayList<String>
Вот почему вы получаете ошибку. Параметр универсального типа класса не является Разрешено в статическом контексте!источник
@BD в Ривенхилле: Так как этот старый вопрос привлек к себе новое внимание в прошлом году, давайте немного поговорим ради обсуждения. Тело вашего
doIt
метода вообще ничего не делаетT
. Вот:Таким образом, вы можете полностью удалить все переменные типа и просто код
Хорошо. Но вернемся ближе к исходной проблеме. Первая переменная типа в объявлении класса является избыточной. Нужен только второй метод. Здесь мы идем снова, но это еще не окончательный ответ:
Тем не менее, это слишком много шума ни о чем, так как следующая версия работает точно так же. Все, что ему нужно, это тип интерфейса для параметра метода. Никаких переменных типа не видно нигде. Была ли это действительно оригинальная проблема?
источник
Так как статические переменные являются общими для всех экземпляров класса. Например, если у вас есть следующий код
T доступен только после создания экземпляра. Но статические методы можно использовать даже до того, как будут доступны экземпляры. Таким образом, на параметры общего типа нельзя ссылаться внутри статических методов и переменных.
источник