До настоящего момента мы рассматривали параметризацию целых классов, однако параметризация может применяться и к отдельным методам классов. Сам класс при этом может быть параметризованным, а может и не быть — это не зависит от наличия параметризованных методов. Параметризованный метод может изменяться независимо от класса. В общем случае параметризованные методы следует использовать «по мере возможности». Иначе говоря, если возможно параметризовать метод вместо целого класса, вероятно, стоит выбрать именно этот вариант. Кроме того, статические методы не имеют доступа к параметрам типа параметризованных классов; если такие методы должны использовать параметризацию, это должно происходить на уровне метода, а не на уровне класса. Чтобы определить параметризованный метод, следует указать список параметров перед возвращаемым значением:
//: generics/GenericMethods.java
public class GenericMethods {
public <T> void f(T x) {
System.out.println(x.getClass().getName());
}
public static void main(String[] args) {
GenericMethods gm = new GenericMethods();
gm.f("");
gm.f(1);
gm.f(1.0);
gm.f(1.0F);
gm.f('c');
gm.f(gm);
}
}
<spoiler text="Output:">
java.lang.String
java.lang.Integer
java.lang.Double
java.lang.Float
java.lang.Character
GenericMethods
</spoiler> Класс GenericMethods не параметризован, хотя и класс, и его методы могут быть параметризованными одновременно. Но в данном случае только метод f() имеет параметр типа, обозначаемый списком параметров перед возвращаемым значением метода. Учтите, что при использовании параметризованного класса параметры типов должны указываться при создании экземпляра. Но при использовании параметризованного метода указывать параметры типа не обязательно, потому что компилятор способен «вычислить» их за вас. Таким образом, вызов f() выглядит как обычный вызов метода; создается впечатление, что метод f() существует в бесконечном количестве перегруженных версий. При вызове ему даже может передаваться аргумент типа GenericMethods. Для вызовов f(), использующих примитивные типы, в действие вступает механизм автоматической упаковки — примитивные типы автоматически преобразуются в соответствующие объекты. Это позволяет исключить некоторые фрагменты кода, которые были необходимы прежде из-за явного выполнения преобразований.