Вызов статического метода с использованием универсального типа - PullRequest
10 голосов
/ 28 июня 2011

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

abstract class Agent<A>{
    void callAgent();
    Agent(){
        A.add();                    
    }
}

Здесь add () - статический метод.

Есть несколько вопросов и ответов по C # по аналогичной теме, но я не совсем уверен, как поступитьэто на Java.

Ответы [ 6 ]

7 голосов
/ 28 июня 2011

Нет, вы не можете сделать это, если A является универсальным типом.(Божо ответил быстро :) и, вероятно, подумал, что это был конкретный тип.

Будет работать следующее.

abstract class Agent extends Blah<ConcreteA>{
    void callAgent();
    Agent() {
        ConcreteA.add();
    }
}

, но это, вероятно, не то, что вы хотите сделать.

После прочтения ваших комментариев это звучит так:

abstract class Agent<A extends SomeClassThatSupportsAdd> {

    void callAgent();
    protected abstract A createNew();

    Agent() {
        A a = createNew();
        A.add();
    }
}

Ваши подклассы должны будут переопределить createNew().

Если вам все еще не нравится этовы можете взглянуть на AspectJ, который позволит вам использовать магию конструктора (посмотрите, как spring делает @Configurable), но это становится намного сложнее и усложняет вещи.

Другой вариант - Scala.Java не наследует статические методы, поэтому вы не можете получить параметризованные модули (группы функций в некоторых языках это называется функтором ... ocaml).Однако Scala поддерживает одноэлементный «объект», который допускает параметрическое функциональное полиморфное наследование.

6 голосов
/ 28 июня 2011

Нет, вы не можете.Компилятор не знает, что A (который разрешается в Object) имеет метод add.

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

Технически вы также можете вызывать статический метод таким образом, но это уродливо:

class Base {
    public static void add() { }
}

class Foo<A extends Base> {
    void bar() {
        A a = null; // you can't use new A()!
        a.add();
    }
}
2 голосов
/ 28 июня 2011

Это невозможно, поскольку тип A не обязательно будет содержать метод add(). Компилятор не допустит этого, потому что не может гарантировать, что он будет работать.

1 голос
/ 19 марта 2016

Фактически, вы можете вызывать статический метод для параметра типа (хотя это не выполняется динамически).

Попробуйте это:

public class Main<T extends Collections> {

    public static void main(String[] args) {
        new Main<>().foo();
    }

    void foo() {
        List<Integer> list = Arrays.asList(2, 3, 1);
        T.sort(list);
        System.out.println(list);
    }
}

Я понятия не имею, почему разработчики языка решили, что это хорошая идея - разрешить это.

0 голосов
/ 04 марта 2019

Вы можете использовать отражение для вызова статического метода класса T. Например:

public Agent<T>{

    private final Class<T> clazz;

    public Agent(Class<T> clazz){
        this.clazz = clazz;
        executeAddMethodOfGenericClass();
    }

    public void executeAddMethodOfGenericClass() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Method method = clazz.getMethod("add");
        method.invoke(null);
    }
}

Но я могу получить исключение. Будьте осторожны.

0 голосов
/ 09 января 2018

Удобно получить значение из перечисления, которое вы не знаете заранее.

public static <T extends Enum<T>> T enumFromName(String name, Class<T> clazz) {
    return StringUtils.isEmpty(value) ? null : T.valueOf(clazz, name);
}

Имея:

enum ProductType { FOOD, ELECTRONICS, ... }

Вы можете сделать:

Полагаю, вы также можете воспользоваться этим в своих классах, хотя я бы не рекомендовал слишком много использовать static.

...