Параметризовать статический метод java

Как параметризовать статический метод в дженериках Java? Как они типизируются?

Дженерики в Java существуют только во время компиляции. Это значит, что во время выполнения нельзя достать из них информацию. Поэтому, чтобы параметризовать метод, нужно передать ему объект, в котором будет содержаться информация о типе. Это может быть либо просто объект этого типа или объект-класс.

Если передаётся класс и в методе происходит создание объекта или вызов методов у него, придётся обрабатывать ситуации, когда конструктор или метод отсутствует или к ним нет доступа.

public static T myMethod(Class aClass) throws ReflectiveOperationException < return aClass.newInstance(); >public static void main(String[] args) < try < String a = myMethod(String.class); System.out.println(a.length()); >catch (ReflectiveOperationException e) < e.printStackTrace(); >>

Для более удобного доступа к свойствам и методам можно использовать commons-beanutils, для вызова конструктора — ConstructorUtils из той же библиотеки или из commons-lang3, а с помощью Optional можно спрятать все исключения под капотом, не выбрасывая null.

import org.apache.commons.lang3.reflect.ConstructorUtils; import java.lang.reflect.Constructor; import java.util.Objects; import java.util.Optional; public class Foo < public static Optional bar(Class aClass) < Constructorctor = ConstructorUtils.getAccessibleConstructor(aClass); if (Objects.nonNull(ctor)) < try < return Optional.of(ctor.newInstance()); >catch (ReflectiveOperationException e) < return Optional.empty(); >> else < return Optional.empty(); >> public static void main(String[] args) < Optionala = bar(String.class); if (a.isPresent()) < System.out.println(a.get().length()); >> >

Источник

Как параметризировать статический метод java

Вы можете параметризовать статический метод передавая ему в качестве аргумента обобщенный тип. Например, рассмотрим следующий пример статического метода, который суммирует два числа:

public class MathUtils  public static int sum(int a, int b)  return a + b; > > 

Вы можете параметризовать этот метод, передав ему в качестве аргументов два объекта типа T , где T — это обобщенный тип, как показано в следующем примере:

public class MathUtils  public static T extends Number> double sum(T a, T b)  return a.doubleValue() + b.doubleValue(); > > 

В этом примере мы использовали обобщенный тип для параметризации метода sum() . Здесь мы ограничиваем тип T , чтобы он был типом Number или его подклассом, и таким образом мы можем использовать метод doubleValue() для преобразования значения объектов типа T в тип double

Таким образом, мы можем вызвать параметризованный статический метод sum() следующим образом:

int result = MathUtils.Double>sum(3.5, 2.5); // 6.0 

Здесь мы явно указываем, что тип T является типом Double

Источник

Дженерики Java

Дженерики (или обобщения) — это параметризованные типы.

Параметризованные типы позволяют объявлять классы, интерфейсы и методы, где тип данных, которыми они оперируют, указан в виде параметра. Используя дженерики, можно создать единственный класс, например, который будет автоматически работать с разными типами данных.

Классы, интерфейсы или методы, имеющие дело с параметризованными типами, называются параметризованными или обобщениями, параметризованными (обобщенными) классами или параметризованными (обобщёнными) методами.

Обобщения добавили в язык безопасность типов.

1. Параметризованные классы

Следующий пример демонстрирует использование параметризованного класса, который описывает матрицу:

public class Matrix  < private T[] array; public Matrix(T[] array) < this.array = array.clone(); >public static void main(String[] args) < MatrixdoubleMatrix = new Matrix<>(new Double[2]); Matrix integerMatrix = new Matrix<>(new Integer[4]); Matrix byteMatrix = new Matrix<>(new Byte[7]); > > 

В объявлении Matrix integerMatrix Integer является аргументом типа.

Java не создает разные версии класса Matrix или любого другого параметризованного класса. Имеется только одна версия класса Matrix , которая существует в прикладной программе.

Дженерики работают только с объектами! Следующий код является неправильным:

Gen strOb = new Gen (53); // Ошибка, нельзя использовать примитивные типы 

Т обозначает имя параметра типа. Это имя используется в качестве заполнителя вместо которого в дальнейшем подставляется имя конкретного типа, передаваемого классу Matrix при создании объекта. Это означает, что обозначение Т применяется в классе Matrix всякий раз, когда требуется параметр типа. Всякий раз, когда объявляется параметр типа, он указывается в угловых скобках.

Обобщенные типы отличаются в зависимости от типов-аргументов. Следующий код не допустим:

doubleMatrix = integerMatrix; // Не верно! 

Несмотря на то, что doubleMatrix и integerMatrix имеют тип Matrix , они являются ссылками на разные типы, потому что типы их параметров отличаются.

Обобщенный класс может быть объявлен с любым количеством параметров типа. Например:

public class TwoGen  < private T obT; private V obV; public TwoGen(T obT, V obV) < this.obT = obT; this.obV = obV; >public void showTypes() < System.out.println("Тип T: " + obT.getClass().getName()); System.out.println("Тип V: " + obV.getClass().getName()); >public T getObT() < return obT; >public V getObV() < return obV; >> public class SimpleGen < public static void main(String[] args) < TwoGentwoGen = new TwoGen<>(88, "Generics"); twoGen.showTypes(); System.out.println("Значение T: " + twoGen.getObT()); System.out.println("Значение V: " + twoGen.getObV()); > > 

2. Ограниченные типы

Указывая параметр типа, можно наложить ограничение сверху в виде верхней границы, где объявляется супер класс, от которого должны быть унаследованы все аргументы типов. С этой целью вместе с параметром указывается ключевое слово extends :

Параметр типа Т может быть заменен только указанным супер классом или его подклассами.

Рассмотрим пример использования ограниченного типа:

public class Average  < private T[] array; public Average(T[] array) < this.array = array; >public double average() < double sum = 0.0; for (T value : array) < sum += value.doubleValue(); >return sum / array.length; > > public class AverageDemo < public static void main(String[] args) < Integer[] intArray = ; Average integerAverage = new Average<>(intArray); System.out.println("Среднее значения для Integer " + integerAverage.average()); Double[] doubleArray = ; Average doubleAverage = new Average<>(doubleArray); System.out.println("Среднее значения для Double " + doubleAverage.average()); // Не откомпилируется, // потому что String не является наследником Number /* String[] strArray = ; Average strAverage = new Average<>(strArray); System.out.println("Среднее значения для String " + strAverage.average());*/ > >

В виде ограничения можно накладывать не только тип класса, но и тип интерфейса:

Ограничение может включать в себя как тип класса, так и типы одного или нескольких интерфейсов:

Тип класса должен быть задан первым. Накладывая на обобщенный тип ограничение, состоящее из класса и одного или нескольких интерфейсов, для их объединения следует воспользоваться логической операцией &: Таким образом, любой тип, передаваемый параметру Т , должен быть подклассом, производным от класса MyClass и реализующим интерфейсы MyInterface1 и MyInterface2 .

3. Применение метасимвольных аргументов

Представьте, что мы хотим добавить метод для сравнения средних значений массивов в класс Average из примера 3. Причем типы массивов могут быть разные:

Integer intArray[] = ; Double doubleArray[] = ; Average iob = new Average<>(intArray); Average dob = new Average<>(doubleArray); if (iob.sameAvg(dob)) < System.out.println("are the same.");>else

Так как Average параметризованный тип, какой тип параметра вы укажете для Average , когда создадите параметр метода типа Average ? Напрашивается следующий вариант:

boolean sameAvg(Average ob)

Но это не сработает, так как в этом случае метод sameAvg будет принимать аргументы только того же типа, что и существующий объект:

Чтобы создать обобщенную версию метода sameAvg() , следует воспользоваться другим средством обобщений Jаvа – метасимвольным аргументом. Метасимвольный аргумент обозначается знаком ? и представляет неизвестный тип.

boolean sameAvg(Average ob)

Мета символ не оказывает никакого влияния на тип создаваемых объектов класса Average . Это определяется оператором extends в объявлении класса Average. Мета символ просто совпадает с любым достоверным объектом класса Average .

Метасимвольные аргументы могут быть ограничены почти таким же образом, как и параметры типов. Ограничивать метасимвольный аргумент особенно важно при создании обобщенного типа, оперирующего иерархией классов. Например:

public class Average2  < private T[] array; public Average2(T[] array) < this.array = array.clone(); >public double average() < double sum = 0.0; for (T value : array) < sum += value.doubleValue(); >return sum / array.length; > boolean sameAvg(Average2 ) < System.out.println("object is instance of GenericSuper"); >if (object instanceof GenericSub[] gens = new GenericSub[10]; gens[0] = new GenericSub<>(34); > >

3. Нельзя создавать обобщенные статические переменные и методы. Но объявить статические обобщенные методы со своими параметрами типа все же можно:

public class GenericWrongStatic < // Неверно, нельзя создать статические переменные типа Т. //public static Т оb; // Неверно, ни один статический метод не может использовать Т. /* public static T getOb() < return оb; >*/ //Но объявить статические обобщенные методы со своими параметрами типа можно public static void getOb(V v) < System.out.println(v); >>

Источник

Как параметризовать статический метод в дженериках Java? Как они типизируются?

Дженерики в Java существуют только во время компиляции. Это значит, что во время выполнения нельзя достать из них информацию. Поэтому, чтобы параметризовать метод, нужно передать ему объект, в котором будет содержаться информация о типе. Это может быть либо просто объект этого типа или объект-класс.

Если передаётся класс и в методе происходит создание объекта или вызов методов у него, придётся обрабатывать ситуации, когда конструктор или метод отсутствует или к ним нет доступа.

public static T myMethod(Class aClass) throws ReflectiveOperationException < return aClass.newInstance(); >public static void main(String[] args) < try < String a = myMethod(String.class); System.out.println(a.length()); >catch (ReflectiveOperationException e) < e.printStackTrace(); >>

Для более удобного доступа к свойствам и методам можно использовать commons-beanutils, для вызова конструктора — ConstructorUtils из той же библиотеки или из commons-lang3, а с помощью Optional можно спрятать все исключения под капотом, не выбрасывая null.

import org.apache.commons.lang3.reflect.ConstructorUtils; import java.lang.reflect.Constructor; import java.util.Objects; import java.util.Optional; public class Foo < public static Optional bar(Class aClass) < Constructorctor = ConstructorUtils.getAccessibleConstructor(aClass); if (Objects.nonNull(ctor)) < try < return Optional.of(ctor.newInstance()); >catch (ReflectiveOperationException e) < return Optional.empty(); >> else < return Optional.empty(); >> public static void main(String[] args) < Optionala = bar(String.class); if (a.isPresent()) < System.out.println(a.get().length()); >> >

Источник

Читайте также:  Python start excel macros
Оцените статью